【题目大意】
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度。
【manacher知识点】
①mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有 P[i] = P[j]。
②当 P[j] > mx - i 的时候,以S[j]为中心的回文子串不完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以 S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,就只能一个一个匹配了。
③对于 mx <= i 的情况,无法对 P[i]做更多的假设,只能P[i] = 1,然后再去匹配了
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 using namespace std; 7 const int MAXN=110000+50; 8 char str[MAXN],s[MAXN*2]; 9 int p[MAXN*2]; 10 11 void init() 12 { 13 s[0]=‘$‘;s[1]=‘#‘; 14 int j=1; 15 for (int i=0;str[i];i++) 16 { 17 s[++j]=str[i]; 18 s[++j]=‘#‘; 19 } 20 //cout<<s<<endl; 21 } 22 23 void solve() 24 { 25 int mx=0,mxid=0; 26 memset(p,0,sizeof(p)); 27 for (int i=1;s[i];i++) 28 { 29 if (mx>i) p[i]=(p[2*mxid-i]<(mx-i)?p[2*mxid-i]:(mx-i)); 30 else p[i]=1; 31 while(s[i-p[i]]==s[i+p[i]]) p[i]++; 32 if (i+p[i]>mx) 33 { 34 mx=i+p[i]; 35 mxid=i; 36 } 37 } 38 } 39 40 int getans() 41 { 42 int len=strlen(str)*2+2; 43 int ans=-1; 44 for (int i=1;i<len;i++) ans=max(ans,p[i]); 45 ans--; 46 return ans; 47 } 48 49 int main() 50 { 51 while (scanf("%s",str)!=EOF) 52 { 53 init(); 54 solve(); 55 cout<<getans()<<endl; 56 } 57 return 0; 58 }
时间: 2024-12-28 20:24:52