#1032 : 最长回文子串
时间限制:1000ms
单点时限:1000ms
内存限制:64MB
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
- 样例输入
-
3 abababa aaaabaa acacdas
- 样例输出
-
7 5 3
题解:
Manacher算法--O(n)回文子串算法
直接转一个大牛的思路,讲的很好:
http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/
http://acm.hust.edu.cn/vjudge/problem/viewSource.action?id=140283
结果:Accepted 提交时间:2015-05-07 14:11:06
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <stack> 6 #include <cctype> 7 #include <vector> 8 #include <cmath> 9 10 #define ll long long 11 12 using namespace std; 13 14 const int M = 21; 15 const int N = 1000010; 16 const ll mod = 1000000007; 17 18 int T; 19 char te[N]; 20 char s[2*N]; 21 int p[2*N]; 22 int ans; 23 int l; 24 25 void pre() //为了防止字符比较的时候越界,我在这个加了‘#’的字符串之前还加了另一个特殊字符‘$’,故我的新串下标是从1开始的 26 { 27 int l1=strlen(te); 28 l=2*l1+2; 29 s[0]=‘$‘; 30 s[1]=‘#‘; 31 for(int i=0;i<l1;i++){ 32 s[i*2+2]=te[i]; 33 s[i*2+3]=‘#‘; 34 } 35 s[l]=‘\0‘; 36 } 37 38 void Manacher() 39 { 40 int i,mx,id; //我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。 41 mx=0; 42 for(i=1;i<l;i++){ 43 if(mx>i){ 44 p[i]=min(p[2*id-i],mx-i); 45 } 46 else{ 47 p[i]=1; 48 } 49 for(;s[ i+p[i] ]==s[ i-p[i] ];p[i]++){ 50 if(i+p[i]>mx){ 51 mx=i+p[i]; 52 id=i; 53 } 54 } 55 } 56 } 57 58 int main() 59 { 60 //freopen("data.in","r",stdin); 61 scanf("%d",&T); 62 for(int ccnt=1;ccnt<=T;ccnt++){ 63 //while(scanf("%d%d",&a,&b) != EOF) { 64 scanf("%s",te); 65 pre(); 66 Manacher(); 67 int i; 68 ans=1; 69 for(i=1;i<l;i++){ 70 ans=max(ans,p[i]-1); 71 } 72 printf("%d\n",ans); 73 } 74 return 0; 75 }
时间: 2024-10-11 23:30:50