【题解】 bzoj3916: [Baltic2014]friends (字符串Hash)

博客针对字符串处理问题给出解决方案。先判断字符串长度为偶数的情况,再枚举删除位置,通过预处理的hash判断剩余部分能否划分成两个相同部分。同时说明了判断重复答案的方法,最后给出代码相关信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面戳我

Solution

  • 首先长度为偶数可以直接判掉
  • 然后我们可以枚举删的位置,通过预处理的\(hash\),判断剩余部分是否划分成两个一样的
  • 判重要注意,我们把字符串分为三个部分\(L_l+1+L_r\),(\(L_l=L_r\)),如果上次答案和这次都出现在\(L_l\),则一定不会是不同的,因为右边的\(L_r\)是一样的,所以复制的串一定是一样的,全在\(L_r\)同理
  • 那么我们就只用判断上次出现的答案在\(L_l+1\)上,这次出现在\(L_r\)上,其实我们就可以发现复制的串变成了\(L_l\),那么我们就只用用\(Hash\)判断\(L_l\)\(L_r\)是否相同即可,不同才是\(Unique\)
  • 上面这种情况让我\(wa\)了好久
  • 貌似又是一次跑的没暴力快qwq

Code

//It is coded by ning_mew on 7.25
#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn=2e6+7;

LL MOD[3]={19260817,20000909,19491001};
LL Hash[3][maxn],Pow[3][maxn];
LL ans=0,L,n;
char ch[maxn];

bool check(int pl){
    for(int k=0;k<3;k++){
        LL box=Hash[k][n],box1=0,box2=0;
        if(pl==L+1){
            box1=Hash[k][L];
            box2=((Hash[k][n]-Hash[k][L+1]*Pow[k][L]%MOD[k])%MOD[k]+MOD[k])%MOD[k];
        }
        else if(pl<=L){
            box2=((Hash[k][n]-Hash[k][L+1]*Pow[k][L]%MOD[k])%MOD[k]+MOD[k])%MOD[k];
            box1=((Hash[k][L+1]-Hash[k][pl]*Pow[k][L+1-pl]%MOD[k]+Hash[k][pl-1]*Pow[k][L+1-pl]%MOD[k])%MOD[k]+MOD[k])%MOD[k];
        }else{
            box1=Hash[k][L];
            box2=((Hash[k][n]-Hash[k][pl]*Pow[k][n-pl]%MOD[k]+(Hash[k][pl-1]-Hash[k][L]*Pow[k][pl-1-L]%MOD[k])*Pow[k][n-pl])%MOD[k]+MOD[k])%MOD[k];
        }
        if(box1!=box2)return false;
    }return true;
}
bool unique(int pl){
    for(int k=0;k<3;k++){
        LL box1=((Hash[k][pl]-Hash[k][L+1]*Pow[k][pl-L-1])%MOD[k]+MOD[k])%MOD[k];
        LL box2=((Hash[k][pl-1]-Hash[k][L]*Pow[k][pl-L-1])%MOD[k]+MOD[k])%MOD[k];
        if(box1!=box2)return false;
    }return true;
}
int main(){
    scanf("%lld",&n);
    if(n%2==0){printf("NOT POSSIBLE\n");return 0;}
    L=(n-1)/2;
    scanf("%s",ch+1);
    for(int k=0;k<3;k++){
        Pow[k][0]=1;Hash[k][0]=0;
        for(int i=1;i<=n;i++){
            Hash[k][i]=(Hash[k][i-1]*237+ch[i]-'A')%MOD[k];
            Pow[k][i]=Pow[k][i-1]*237%MOD[k];
        }
    }
    for(int i=1;i<=n;i++){
        if(check(i)){
            if(!ans)ans=i;
            else{
                if((ans<=L+1&&i>L+1)){
                    if(!unique(i)){
                        printf("NOT UNIQUE\n");
                        return 0;
                    }
                }
            }
        }
    }
    if(!ans){printf("NOT POSSIBLE\n");return 0;}
    else {
        int box=0;
        for(int i=1;i<=n;i++){
            if(i!=ans&&box<(n-1)/2){printf("%c",ch[i]);box++;}
        }
    }return 0;
}

博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/Ning-Mew/,否则你会场场比赛爆0!!!

转载于:https://www.cnblogs.com/Ning-Mew/p/9364747.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值