题意很简单,给你一个字符串,要求你求出一个最长的形似于w(wr)w(wr)的最长连续子串的长度。wr表示w的逆序串。
在这里大家很容易就能想到Manacher算法求回文串。没有错,就是这个。
算法的详细过程我就不说了,直接说后面的实现吧。
通过manacher算法我们可以在O(N)的时间复杂度以内求出一每两个字符空缺处为对称轴的最长回文串的长度。
这样我们可以对于每一个空缺位置逐一枚举,然后分别对匹配求出一个最长的回文串就可以了。
中间有好多细节要优化哦,我wa了好几发。还有在写的时候一定要写出各种优化。代码不要写挫了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #define maxn 1000100 5 using namespace std; 6 7 char tep[maxn],s[2*maxn]; 8 int a[2*maxn],n,ans,now; 9 10 void init() 11 { 12 now=2; 13 s[0]='@'; 14 s[1]='#'; 15 for (int i=0; tep[i]; i++) 16 { 17 s[now++]=tep[i]; 18 s[now++]='#'; 19 } 20 s[now]='$'; 21 s[now+1]=0; 22 } 23 24 void deal() 25 { 26 memset(a,0,sizeof a); 27 int mx_c=0,mx_r=0; 28 a[0]=1; 29 for (int i=1; i<now; i++) 30 { 31 if (mx_r>i) 32 { 33 a[i]=min(mx_r-i+1,a[2*mx_c-i]); 34 } 35 else a[i]=1; 36 while (s[i-a[i]]==s[i+a[i]]) a[i]++; 37 if (i+a[i]>mx_r) mx_r=i+a[i]-1,mx_c=i; 38 } 39 } 40 41 int main() 42 { 43 int cas; 44 scanf("%d",&cas); 45 while (cas--) 46 { 47 scanf("%s",tep); 48 for (int i=0; tep[i]; i++) 49 if (tep[i]>='A' && tep[i]<='Z') 50 tep[i]=tep[i]-'A'+'a'; 51 ans=0; 52 init(); 53 deal(); 56 for (int i=1; s[i]; i+=2)//这里一定是+2,只有空缺处才是满足条件的。 57 { 58 int cur=a[i]-1; 59 while (cur%4!=0 || cur/2>=i) cur--; 60 for (; cur>ans; cur-=4) 61 { 62 if (a[i+cur/2]>=cur/2+1 && a[i-cur/2]>=cur/2+1) 63 { 64 ans=cur; 65 break; 66 } 67 } 72 } 73 printf("%d ",ans); 74 } 75 return 0; 76 }