【题解】 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\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!!!

posted @ 2018-08-25 19:31  Ning_Mew  阅读(188)  评论(0编辑  收藏  举报