标签:
时间限制: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
这一道题目的关键:
1、是采用Manacher算法来进行求解最长回文字符串,时间复杂度为O(N)。
2、本题目在数据最大时候可以达到1000000。所以为了防止构造新的字符串时候浪费大量时间所以我们对数组进行预先分配内存。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
static string afterProcessStr(1000002*2,‘#‘);//预先分配内存并进行初始化
int preprocess(string &str)//预处理时候只要把奇数位置的‘#’替换了就好!
{
//string afterProcessStr="#";
for(int i=0;i<str.size();++i)
{
afterProcessStr [2*i+1]= str[i];
}
return str.size()*2+1;
//afterProcessStr.clear();
}
int maxpalindrome(string &str)
{
int sizeStr=preprocess(str);
// cout<<afterProcessStr<<endl;
int maxEdge=0,center=0;
int *p=new int[sizeStr]();
int ans=0;
for(int i=1;i<sizeStr;++i)
{
p[i]=(maxEdge>i)?min(maxEdge-i,p[2*center-i]):0;
while(i-1-p[i]>=0&&i+1+p[i]<sizeStr&&afterProcessStr[i+1+p[i]]==afterProcessStr[i-1-p[i]])
++p[i];
if(i+p[i]>maxEdge)
{
center=i;
maxEdge=i+p[i];
}
if(p[i]>ans)
ans=p[i];
}
return ans;
}
int main()
{
int tn;
cin>>tn;
string str;
str.reserve(1000002);
int ans,tmp;
for(int ye=0;ye<tn;++ye)
{
cin>>str;
cout<<maxpalindrome(str)<<endl;
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/zhouyelihua/article/details/46964175