这个有好多种方法,每个方法复杂度也不一样。
1.暴力,复杂度是O(n^3),就是循环需要两层,O(n^2),每次判断是否是回文数复杂度为O(n)。
2.序列a和它的反转序列b,求他们的最长公共子序列,而且必须要求这个最长公共子序列是回文的,复杂度为O(n^2)
3.动态规划,p[i][j] 表示i开头j结尾的字符串,=true代表是回文,如果p[i][j]是true的条件是p[i+1][j-1]是true和a[i] == a[j]
代码:
<span style="font-family:Courier New;font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
char a[1005];
bool p[1005][1005];
int main()
{
int n,i,len;
while(cin >> a)
{
int max = 1;
int start = 0;
memset(p,0,sizeof(p));
int length = strlen(a);
for(i=0; i<length-1; i++)
{
p[i][i] = true;//true代表i到j的字符串是回文的
if(a[i] == a[i+1])
{
start = i;
max = 2;
p[i][i+1] = true;
}
}
p[length-1][length-1] = true;
for(len=3; len<=length; len++)//这里必须是从3开始的
{
for(i=0; i<=length-len; i++)
{
int j = len + i - 1;
if(a[i] == a[j] && p[i+1][j-1])
{
p[i][j] = p[i+1][j-1];//这里的i+1和j-1的操作使得len必须从3开始
max = len;
start = i;
}
}
}
cout << max << endl << start << endl;
if(max > 1)
for(i=start; i<=start+max-1; i++)
cout << a[i];
cout << endl;
}
return 0;
} </span>
4.可以对该字符串的每个元素进行遍历,以当前访问的字符作为中心,向两边扩展,保存最大的回文字符串长度,这个方法也是O(n^2),奇数偶数需要分别进行讨论。
5.manacher(这个方法才是最该掌握的),这个方法复杂度为O(n),题目一般要求的都是特别大的序列,manacher最快速。
它的思想个中心法类似。对源字符串str[n]做处理,比如n个字符,则加上n+1个字符‘#’,处理后为数组temp[2*n+1],len[i]数组用来记录以i为中心的时候,i位置到最大回文字符串最右端的距离,即mx-i(mx为最右端的后面那个字符)。所以总的字符串长度为2*len[i] - 1,由于‘#’比字符多1,所以源字符串最大回文字符串为len[i]-1,具体分析参考点击打开链接
代码:(hdu 3068)
<span style="font-family:Courier New;font-size:18px;">#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define ma 1100005
char str[ma];
char temp[2*ma];
int leng[2*ma];
void init()
{
int len = strlen(str+1);
int i;
for(i=1; i<=2*len; i+=2)
{
temp[i] = '#';
temp[i+1] = str[(i+1)/2];
}
temp[0] = '$';
temp[2*len+1] = '#';
temp[2*len+2] = '_';
// cout << temp << endl;
return ;
}
int manacher()
{
int mx = 0,p = 0,i;//mx是当前 匹配的最大回文子串的最右端后面那个位置
int ans = 1;
int len = strlen(str+1);
for(i=1; i<=len*2; i++)
{
if(i < mx)
leng[i] = min(mx-i,leng[2*p-i]);//看i关于p的对称位置j的leng[j]是否大于mx-i如果大于则证明i目前的
//最长回文是mx-i,f否则最长回文是length[j]
else
leng[i] = 1;
while(temp[i-leng[i]] == temp[i+leng[i]])
leng[i]++;
if(leng[i]+i > mx)
{
mx = leng[i] + i;
p = i;
//printf("***%d * %d ***\n",mx,p);
}
ans = max(ans,leng[i]-1);
}
//cout << mx << endl;
//cout << " p = " << p << " ";
cout << ans << endl;
return ans;
}
int main()
{
int n;
while((cin >> str+1))
{
//cin >> str+1;
init();
manacher();
}
return 0;
} </span>