【BZOJ】【2565】最长双回文串

Manacher算法


  找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少……

  同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r[i]分别表示从 i 这个位置开始向左/右最长的回文串有多长,那么我们枚举两个回文串的分割点更新答案即可。

 1 /**************************************************************
 2     Problem: 2565
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:80 ms
 7     Memory:4496 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2565
11 #include<cstdio>
12 #include<cstring>
13 #include<cstdlib>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20 typedef long long LL;
21 inline int getint(){
22     int r=1,v=0; char ch=getchar();
23     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
24     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
25     return r*v;
26 }
27 const int N=1e5+10,INF=~0u>>2;
28 /*******************template********************/
29 char s[N];
30 int p[N<<1],a[N<<1],l[N<<1],r[N<<1],n;
31 int main(){
32     scanf("%s",s);
33     n=strlen(s);
34     F(i,1,n) a[i<<1]=s[i-1];
35     n=n<<1|1;
36  
37     int id=0,mx=0;
38     F(i,1,n){
39         if (mx>i) p[i]=min(p[2*id-i],mx-i);
40         while(i-p[i]-1>0 && i+p[i]+1<=n && a[i-p[i]-1]==a[i+p[i]+1]){
41             p[i]++;
42             l[i+p[i]]=max(l[i+p[i]],p[i]);
43             r[i-p[i]]=max(r[i-p[i]],p[i]);
44         }
45         if (p[i]+i>mx) mx=p[i]+i,id=i;
46         l[i+p[i]]=max(l[i+p[i]],p[i]);
47         r[i-p[i]]=max(r[i-p[i]],p[i]);
48     }
49     /*
50     F(i,1,n) printf("%c ",a[i]!=0?a[i]:'#'); puts("");
51     F(i,1,n) printf("%d ",p[i]); puts("");
52     F(i,1,n) printf("%d ",l[i]); puts("");
53     F(i,1,n) printf("%d ",r[i]); puts("");
54     */
55     int ans=0;
56     F(i,1,n) if(l[i]+r[i]>ans) ans=l[i]+r[i];
57     printf("%d\n",ans);
58     return 0;
59 }
View Code

 

posted @ 2015-04-07 11:32  Tunix  阅读(235)  评论(0编辑  收藏  举报