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


    题面戳我

    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
    ");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
    ");
    						return 0;
    					}
    				}
    			}
    		}
    	}
    	if(!ans){printf("NOT POSSIBLE
    ");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!!!

  • 相关阅读:
    分治思想
    二分查找---查找区间
    二分查找---有序数组的 Single Element
    Ogre碰撞检测
    JavaScript常用检测脚本(正则表达式)
    Js+XML 操作
    C++难点的一些总结
    MFC使用简单总结(便于以后查阅)
    vc中调用Com组件的所有方法详解
    OSG+VS2010+win7环境搭建---OsgEarth编译
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/9364747.html
Copyright © 2020-2023  润新知