如果一个字符串正着读和倒着读是一样的,则称它是回文的。
给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。
把字符串、hash为一个unsigned long long数组里的值,求范围分、字符串可以用前缀或后者表示。
回文就是 前缀+后缀 进行运算。
a~ b ~ c,是不是回文串 == a~b的hash值 是否与 c~b的hash值相等
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N=1000000+10;
typedef unsigned long long int ull;
ull h1[N],h2[N],p[N];
char str[N];
ull hash1(int l,int r){
return h1[r]-h1[l-1]*p[r-l+1];
}
ull hash2(int l,int r){
return h2[l]-h2[r+1]*p[r-l+1];
}
int main(){
int t=1;
while(cin>>str+1 ){
if (strcmp(str+1,"END")==0) //结束读入
return 0;
int n=strlen(str+1);
p[0]=1;
for(int i=1;i<=n;i++){
h1[i]=h1[i-1] *131 + str[i]-'a'+1;
p[i]=p[i-1]*131;
}
h2[n+1]=0;
for(int i=n;i>=1;i--){
h2[i]=h2[i+1] *131 +str[i]-'a'+1;
}
int ans=-1e8;
//二分;
for(int i=1;i<=n;i++){
//先奇数长度;
int l=0,r=min(i-1,n-i);
while(l<r){
int mid=l+r+1>>1;
if(hash1(i-mid,i-1) == hash2(i+1,i+mid)) l=mid;
else r=mid-1;
}
ans = max(l*2+1,ans);
//二分偶数;
l=0,r=min(i,n-i);
while(l<r){
int mid = l+r+1>>1;
if(hash1(i-mid+1,i) == hash2(i+1,i+mid)) l=mid;
else r=mid-1;
}
ans = max (2*l,ans);
}
printf("Case %d: %d\n",t++,ans);
}
return 0;
}