Manacher回文串算法 hdu3068 hdu4513

学习资料:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824

时间复杂度O(N)

模板:

View Code
 1 void Manacher(int n)
 2 {
 3     int i;
 4     int mx=0;//记录前面回文串最长影响到的地方。不一定是最长回文串造成的。
 5     int id;//最长影响串的ID;
 6     p[0]=0;
 7     for(i=1;i<n;i++)
 8     {
 9         p[i]=1;//至少是1
10         if(mx>i)//i受到影响即,id+p[id]-1>=i;
11         {
12             p[i]=p[2*id-i];//2*id-i是i关于id的对称点相当于是id-(i-id);
13             if(mx-i<p[i])p[i]=mx-i;
14             //由于对称点的回文半径可能超过mx-i,因为mx后面的还没有配过
15             //所以要取小的。等等继续配
16         }
17   
18         //向两端配匹
19         while(str[i-p[i]]==str[i+p[i]])p[i]++;
20   
21         if(i+p[i]>mx)
22         {
23             mx=i+p[i];
24             id=i;
25         }
26     }
27 }

hdu3068:求一个字符串的最长回文子串,就是一个满足本身是回文的最长的子串

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 const int M = 110010;
 4 char s[M],str[M*2];
 5 int p[M*2];
 6 int n;
 7 int max(int a,int b){
 8     return a>b?a:b;
 9 }
10 int min(int a,int b){
11     return a<b?a:b;
12 }
13 void init(){
14     int i,j=0;
15     n=strlen(s);
16     str[j++]='$';str[j++]='#';
17     for(i=0;i<n;i++){
18         str[j++]=s[i];
19         str[j++]='#';
20     }
21     str[j]='\0';
22     n=j;
23 }
24 int solve(){
25     int i,id,mx=0;
26     for(i=1;i<n;i++){
27         if(mx>i) p[i]=min(mx-i,p[2*id-i]);
28         else p[i]=1;
29         for(;str[i+p[i]]==str[i-p[i]];p[i]++) ;
30         if(p[i]+i>mx){
31             mx=p[i]+i;
32             id=i;
33         }
34     }
35     int res=0;
36     for(i=1;i<n;i++)
37         res=max(res,p[i]);
38     return res;
39 }
40 int main(){
41     while(scanf("%s",&s)!=EOF){
42         init();
43         printf("%d\n",solve()-1);
44     }
45     return 0;
46 }

hdu4513:

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 const int M = 100010;
 4 int s[M],str[M*2];
 5 int p[M*2];
 6 int T,n;
 7 int max(int a,int b){
 8     return a>b?a:b;
 9 }
10 int min(int a,int b){
11     return a<b?a:b;
12 }
13 void init(){
14     int i,j=0;
15     str[j++]=-1;str[j++]=0;
16     for(i=0;i<n;i++){
17         str[j++]=s[i];
18         str[j++]=0;
19     }
20     n=j;
21 }
22 int solve(){
23     int i,id,mx=0;
24     for(i=1;i<n;i++){
25         if(mx>i) p[i]=min(mx-i,p[2*id-i]);
26         else p[i]=1;
27     while(str[i+p[i]]==str[i-p[i]]){
28         if(str[i+p[i]]<10) p[i]++;
29         else {
30             int a=i-p[i];
31                     int b=i+p[i];
32   
33                     if(a+2<=b-2&&str[a]<=str[a+2]&&str[b-2]>=str[b]){
34                             p[i]++;
35                             continue;
36                     }
37                     else if(a==b){
38                             p[i]++;
39                             continue;
40                        }
41             else if(a+2>b-2){
42                             p[i]++;
43                             continue;
44                     }
45                     break;
46                 }
47     }        
48         if(p[i]+i>mx){
49             mx=p[i]+i;
50             id=i;
51         }
52     }
53     int res=0;
54     for(i=2;i<n;i++)
55         res=max(res,p[i]);
56     return res;
57 }
58 int main(){
59     int i;
60     scanf("%d",&T);
61     while(T--){
62         scanf("%d",&n);
63         for(i=0;i<n;i++){
64             scanf("%d",&s[i]);
65         }
66         init();
67         printf("%d\n",solve()-1);
68     }
69     return 0;
70 }

 

posted @ 2013-04-10 20:38  _sunshine  阅读(373)  评论(0编辑  收藏  举报