# 题意
给定一个串,求最长的回文子串
# 题解
一个判定是不是回文串可以用一个长度表示回文半径
枚举每一个点,假设当前点是 i
每次都检查奇数长度和偶数长度
奇数情况下分为 { i-len , i-1 } 和 { i +1 , i+len}
子回文串长度就是2*len+1
偶数情况下分为{ i-len , i-1 } 和 { i , i+len-1 }
遍历每一个点,然后二分回文半径的长度
二分的时候
最小长度应该是0
奇数长度的时候,最大长度应该是开始到当前点前一个点,和当前点后一个点到结尾这两个长度的最小值
偶数长度是当前点前一个点,和当前到最后的最小值
1 #include <bits/stdc++.h> 2 #define ull unsigned long long 3 using namespace std; 4 const int N=1e6+10,P=131; 5 char s[N]; 6 int m; 7 int t; 8 ull h1[N],h2[N],p[N]; 9 ull geth1(int l,int r){ 10 return h1[r]-(h1[l-1]*p[r-l+1]); 11 } 12 ull geth2(int l,int r){ 13 return h2[l]-h2[r+1]*p[r-l+1]; 14 } 15 int main(){ 16 p[0]=1; 17 for(int i=1;i<=N;i++) p[i]=p[i-1]*P; 18 19 while(scanf("%s",s+1) && strcmp(s+1,"END")){ 20 cout<<"Case "<<++t<<": "; 21 int ans=0,len=strlen(s+1); 22 h2[len+1]=0; 23 for(int i=1;i<=len;i++) h1[i]=h1[i-1]*P+(s[i]-'a'+1); 24 for(int i=len;i;i--) h2[i]=h2[i+1]*P+(s[i]-'a'+1); 25 26 for(int i=1;i<=len;i++){ 27 int l=0,r=min(i-1,len-i);//二分的是长度,即到左边和到右边长度的最大值 28 while(l < r){ 29 int mid=l+r+1>>1; 30 if(geth1(i-mid,i-1) == geth2(i+1,i+mid)) 31 l=mid; 32 else 33 r=mid-1; 34 } 35 ans=max(ans,l*2+1); 36 37 l=0,r=min(i-1,len-i+1); //当前点算右半边所以要+1 38 39 while(l<r){ 40 int mid=l+r+1>>1; 41 if(geth1(i-mid,i-1) == geth2(i,i+mid-1)) 42 l=mid; 43 else 44 r=mid-1; 45 } 46 ans=max(ans,l*2); 47 } 48 cout<<ans<<endl; 49 } 50 51 }