HDU 3294(manacher模版题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3294

题意:给定一个字符和一个字符串,求转化后字符串出现的第一个最长回文(即有很多相同长度,输出第一个),并输出起始终点位置,以及转化后的回文串。

题解:manacher算法求得最长回文串的长度mxx以及该回文串的中心位置iid,则s[iid-mxx+1]~s[iid+mxx-1]中去掉#的就是所求串,原位置为(iid-mxx+1)/2-1~(iid+mxx-1)/2-1.

 

代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn =200000+50;
 7 char s[maxn<<1];
 8 int p[maxn<<1];
 9 int mxx,iid;
10 void manacher()
11 {
12     mxx=-1;
13     int len=strlen(s);
14     for(int i=len;i>=0;i--)
15     {
16         s[i+i+2] = s[i];
17         s[i+i+1] = '#';
18     }
19     s[0] = '*';
20     int id,mx=0;
21     for(int i=1;i<len+len+2;i++)
22     {
23         if(mx>1) p[i] = min(p[2*id-i],mx-i);
24         if(p[i]==0) p[i]=1;
25         while(s[i-p[i]]==s[i+p[i]])p[i]++;
26         if(i+p[i]>mx)
27         {
28             mx=i+p[i];
29             id=i;
30         }
31         if(p[i]-1>mxx)
32         {
33             mxx=p[i]-1;
34             iid=i;
35         }
36     }
37 }
38 
39 int main()
40 {
41     char c;
42     while(~scanf("%c%s",&c,s))
43     {
44         getchar();
45         int k = c-'a';
46         int len=strlen(s);
47         
48         for(int i=0;i<len;i++)
49         {
50             s[i]-=k;
51             if(s[i]<'a')
52                 s[i]+=('z'-'a'+1);
53         }
54         manacher();
55         if(mxx==1)
56          printf("No solution!\n");
57         else
58         {
59             printf("%d %d\n",(iid-mxx+1)/2-1,(iid+mxx-1)/2-1);
60             for(int i=(iid-mxx+1);i<=(iid+mxx-1);i++)
61             if(s[i]!='#'&&s[i]!='*')
62             printf("%c",s[i]);
63             printf("\n");
64         }
65     }
66 }
View Code

 

posted on 2015-07-20 11:34  小松song  阅读(760)  评论(0)    收藏  举报

导航