二分法求迴文串

#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const ll p=10000019;
const ll maxn=200010;
ll powp[maxn],h1[maxn],h2[maxn];

void init(){
	powp[0]=1;
	for(int i=1;i<maxn;i++){
		powp[i]=(powp[i-1]*p)%mod;
	}
}
	
void calh(ll h[],string &str){
	h[0]=str[0];
	for(int i=1;i<str.length();i++){
		h[i]=(h[i-1]*p+str[i])%mod;
	}
}

int calsinglesubh(ll h[],int i,int j){
	if(i==0) return h[j];
	return ((h[j]-h[i-1]*powp[j-i+1])%mod+mod)%mod;
}

int binarysearch(int l,int r,int len,int i,int iseven){
	while(l<r){
		int mid=(l+r)/2;
		int h1l=i-mid+iseven,h1r=i;
		int h2l=len-1-(i+mid),h2r=len-1-(i+iseven);//難!
		int hashl=calsinglesubh(h1,h1l,h1r);
		int hashr=calsinglesubh(h2,h2l,h2r); 
		if(hashl!=hashr) r=mid; //說明迴文半徑≤mid 
		else l=mid+1;
	}
	return l-1;
}

int main(){
	init();
	string str;
	getline(cin,str);
	calh(h1,str);
	reverse(str.begin(),str.end());
	calh(h2,str);
	int ans=0;
	//奇迴文 
	for(int i=0;i<str.size();i++){
		int maxlen=min(i,(int)str.length()-1-i)+1;
		int k=binarysearch(0,maxlen,str.length(),i,0);
		ans=max(ans,k*2+1);
	}
	//偶迴文 
	for(int  i=0;i<str.length();i++){
		int maxlen=min(i+1,(int)str.length()-1-i)+1;
		int k=binarysearch(0,maxlen,str.length(),i,1);
		ans=max(ans,k*2);
	}
	printf("%d\n",ans);
	return 0; 
}
	
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章