hiho一下--第一周(最长回文子串)

时间限制: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



hint:就是给你一个字符串,问你这个字符串的最长回文子串的长度是多少。。。
感觉自己又学到了新技能。。。因为处理回文字符串的时候,奇数比偶数处理起来更简单一点,所以我们用一个技巧,在字符的前后加上'#'
求回文串,一般人是枚举。。。但是考虑到数据量的问题,可能会超时,所以换一种方法,把每个字符当做回文串的中点去判断,又因为当所有的字符都相同的时候,这个算法会退化得非常慢,所以我们
想办法,发现利用前面求得的信息,我们在之后求回文串的时候可以省事不少----我们保存当前已经求得的最远回文串以及该回文串的中点,然后判断当前要求的这个位置和最远点的关系和该点的对称点
的回文串长度之间的关系,//http://www.tuicool.com/articles/n6NfIrN 这个链接里面我觉得讲得非常好了。。。。可以观摩学习一波
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<string>
 5 #include<cstring>
 6 using namespace std;
 7 const int N = 1<<23;
 8 char s[N], str[N];
 9 int a[N];
10 
11 //http://www.tuicool.com/articles/n6NfIrN   最长回文子串的一篇文章,讲得可以说是非常好了
12 int main(){
13     int n;
14     scanf("%d", &n);
15     str[0]='$';
16     str[1]='#';
17     while(n--){
18         scanf("%s", s);
19         int n=2;
20         for(int i=0; s[i]; i++){
21             str[n++]=s[i];
22             str[n++]='#';
23         }
24         int mx=0, re;
25         for(int i=1; i<n; i++){
26             if(mx>i) a[i]=min(mx-i, a[2*re-i]);
27             else a[i]=1;
28             while(str[i-a[i]] == str[i+a[i]]) a[i]++;
29             if(i+a[i]>mx){
30                  mx=i+a[i];
31                  re = i;
32             }
33         }
34         int ans=1;
35         for(int i=1; i<n; i++) ans=max(ans, a[i]-1);
36         printf("%d
", ans);
37     }
38 
39     return 0;
40 }
原文地址:https://www.cnblogs.com/ledoc/p/7127725.html