1、判断回文串
回文串就是从左看与从右看都是一样的字符串,例如abcba,acddca
判断一个字符串是否为回文串:如判断s=abcdcba是否为回文串,只要看s以中间位分界线,s的左右两边是否相等即可。令id为s的下标,发现s的左右两边对称的字符的下标号的和等于s.length()-1,例如
如图 比较s[0]和s[8],s[1]和s[7] 发现下标号相加正好等于s的长度减一。
代码:
bool isHunWen(string s)
{
int n=s.length()/2;
for(int i=0;i<n;i++)
{
if(s[i]!=s[s.length()-1-i])
return false;
}
return true;
}
2.最长回文串
最长回文串即一个字符串的子串是回文串,这个回文串最长为多少。
将字符串中每一个字符的左右两边加入一个字符‘#’,一般是这个,字符‘#’必须不在字符串中出现,这样就可以避免讨论了奇数长度字符串和偶数长度字符串,例如字符串abcd,加入‘#’后,#a#b#c#d#,不管原来的是奇数长度还是偶数长度,加入‘#’后都是奇数长度,在第一个‘#’前加入'#'避免边界越界。用数组p[i]表示新字符串中以str(i)字符为中心的最长字符串个数,包括str(i)这个字符,即以str(i)为起点向右移动p[i] 个字符,例如
发现p[i]-1就是原字符在原字符串中的回文长度,于是只要求出p[]数组的各个长度就一扫就知道最长回文子串长度了
那么如何求p呢?
引入mx表示新字符串中回文子串的最右边界,id表示这个回文子串的中心位置,p[id]表示以str[id]为起点,向右一直移动到回文子串的边界处的字符个数,包括str[id],所以mx=id+p[id],令j=2*id-i,则i与j关于id对称,如果mx>i,则p[i]=min(p[2*id-i],mx-i),即p[i]能取到最小值,为什么,借助图来理解:
当mx>i 时,若mx-i>p[j],则mx与i中间的距离变大,以str[j]为中心的回文子串包含在以id为中心的回文字串中,i与j对称,以i为中心的回文子串也包含在以id为中心的回文子串中,,i与j都在向id靠近,p[i]=p[j],若mx-i<=p[i],则i与mx之间距离在变小,以j为中心的回文子串不一定包括在以id为中心的回文子串中,p[i]=mx-i;当mx<=i时候,就一个字符,
p[i]=1。
这个算法就叫做manacher算法,时间复杂度O(n),因为是线性的,p数组不断的向后线性移动
代码如下:
#include<iostream>
//#include<cstring>
#include<vector>
//#include<algorithm>
using namespace std;
const int N=3000000;
int n;
char s[N],str[N];
int p[N];
inline void checkMax(int& ans,int b)
{
if(ans<b)
ans=b;
}
inline int min(int a,int b)
{
if(a>b)
return b;
else
return a;
}
//字符串的匹配,逐步向后移动
void pipei()
{
int mx=0,i,id;
for(i=0;i<n;i++)
{
if(mx>i)
p[i]=min(p[2*id-i],id+p[id]-i);//以id为中心
else
p[i]=1;
for(;str[i+p[i]]==str[i-p[i]];p[i]++)//以i为中心,找到i为中心的回文串,左右两边匹配
;
if(i+p[i]>mx) //以i为中心的
{
mx=i+p[i];
id=i;
}
}
}
void init()
{
int i,j,k;
n=strlen(s);
str[0]='$';
str[1]='#';
for(i=0;i<n;i++)
{
str[i*2+2]=s[i];
str[i*2+3]='#';
}
n=n*2+2;
str[n]=0; //防止边界越界
}
void pt()
{
int ans=0,i;
/*for(i=0;i<n;i++)
cout<<str[i];
puts("");
for(i=0;i<n;i++)
cout<<p[i];
puts("");*/
for(i=0;i<n;i++)
checkMax(ans,p[i]);
cout<<"最长回文串:"<<ans-1<<endl;
}
int main()
{
while(scanf("%s",s)!=EOF)
{
init();
pipei();
pt();
}
return 0;
}
求最长回文串的方法英文文档如:http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html