【manacher】HDU3068-最长回文

【题目大意】

给出一个只由小写英文字符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 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5746883.html