这个是求字符串的最大回文字串,如果按照动态规划的做法,时间复杂度是o(n^2)
这里分享一个时间复杂度为o(n)的做法,因为前不久在leetcode上面看到过,所以做PAT的时候就很快写出来了。
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
const int maxn=1001;
char in[maxn];
bool isSymmetry(char *in,int start,int end){
if(start<0) return false;
while(start<end) {
if(in[start++]!=in[end--]) return false;
}
return true;
}
int main(){
gets(in);
int length=strlen(in);
int len=0,max=-1;
//从左到右遍历字符串,每次只需要考虑加入这个字符是否能组成更长的回文串
for(int i=0;i<length;i++){
if(isSymmetry(in,i-len-1,i)){
len+=2;
//if(len>max) max=len;
}
else if(isSymmetry(in,i-len,i)){
len+=1;
//if(len>max) max=len;
}
}
printf("%d",len);
return 0;
}
可以看到算法的核心思想是从左到右遍历字符串,每次只需要考虑加入这个字符是否能组成更长的回文串。
这里有个思想就是,每次加入一个新的字符,只能使当前考虑过的字符(是从左到右一个一个增加考虑字符)中的最大回文串长度增加1或者2。
因为如果长度增加了三,那个说明,上一次的最大回文串的长度应该是length+1,与length表示每次循环的最大回文串矛盾。
下面是按照字符串长度进行动态规划的代码
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
const int maxn=1001;
char in[maxn];
bool dp[maxn][maxn];
int main(){
gets(in);
int length=strlen(in);
int ans=1;//ans表示最大回文串的长度
//对长度为1或者2的字符串进行初始化
for(int i=0;i<length;i++){
dp[i][i]=1;
if(i<length-1){
if(in[i]==in[i+1]){
dp[i][i+1]=1;
ans=2;
}
}
}
//按照字符串的长度开始动态规划
for(int len=3;len<=length;len++){
for(int i=0;i+len-1<length;i++){
int j=i+len-1;
if(in[i]==in[j]&&dp[i+1][j-1]==1){
dp[i][j]=1;
ans=len;
}
}
}
printf("%d",ans);
return 0;
}