回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。
输入一个字符串Str,输出Str里最长回文子串的长度。
Input
输入Str(Str的长度 <= 100000)
Output
输出最长回文子串的长度L。
Input示例
daabaac
Output示例
5
刚开学有点嗨,居然花了点时间才搞定这个算法,静不下来,太活泼了。
我看了许多关于这个算法的帖子,都看不下去,get不到重点,后来静下来慢慢看才搞定。
说下重点:(代码有注析)
1: 为了忽略单双字符串配对,中间插入符号,为了方便判断边界,开头加入一个不一样的符号
2:最重要的一点!!之前配对已经判断过了,算法核心就是后面算过的可能和前面区间对称,带着这个想法看理解的快一点
看了那么多篇,这篇是对我来说好比较好理解的(个人想法):http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
最后附上代码:
#include <iostream>
#include <algorithm>
#include <string.h>
#include <mem.h>
using namespace std;
char str1[100005],str2[200005];
int leng,i,j,dian=0,maxl=0,ans[200005],maxans=0,left,right;0
int min(int a,int b) //返回较小的数字
{
if(a<b)
return a;
return b;
}
void csh() //初始化
{
ans[0]=1;
str2[0]='&'; //免去判断边界
str2[1]='*';
j=2;
for(i=0;i<leng;i++)
{
str2[j++]=str1[i];
str2[j++]='*';
}
}
void manachar()
{
leng=j; //变化后的数组长度
for(i=1;i<leng;i++)
{
if(i<maxl) //如果少于最长的边界
ans[i]=min(maxl-i,ans[2*dian-i]); //manachar算法思想,对称
else ans[i]=1; //边界外,初始为1,然后进行扩展直到不配对
while(str2[i+ans[i]]==str2[i-ans[i]]) //一直判断直到不配对
ans[i]++;
if(ans[i]>maxans) //更新长度(答案)
maxans=ans[i];
if(ans[i]+i>maxl) //更新最长边界及其中心点
{
dian=i;
maxl=ans[i]+i;
}
}
}
int main()
{
cin>>str1;
leng=strlen(str1);
csh();
manachar();
cout<<maxans-1;
return 0;
}