问题:给定字符串,求其最长回文子串的长度。回文串是形如”aba”, “abba”的对称字符串。例如:字符串“xabcbam”的最长回文字符串长度为5。
这个问题可以用动态规划(DP)来求解,其初始状态和转移方程如下:
实现的代码如下:
#include <stdio.h>
#include <string.h>
#define N 1024 //字符串最大长度
#define max(a, b) ((a) > (b) ? (a) : (b))
int g_cnt[N][N]; // g_cnt[i][j]表示i~j子串中最大回文长度, 默认全部初始化为0
//动态规划求最长回文子串的长度
int dp_maxlen(const char *s){
int slen = strlen(s);
if(slen >= N){
fprintf(stderr, "exceed size:%d\n", N);
return -1;
}
//长度为1的子串都是回文
for(int i = 0; i < slen; ++i){
g_cnt[i][i] = 1;
}
for(int len = 2; len <= slen; ++len){ //长度从小到大处理子串
for(int i = 0; i < slen; ++i){
int left = i;
int right = i + len - 1;
if( left < 0 || right >= slen){
continue;
}
//左右两个字符相等,且中间部分也是回文
if(s[left] == s[right] && g_cnt[left + 1][right - 1] == len - 2){
g_cnt[left][right] = g_cnt[left + 1][right - 1] + 2;
}
else{
g_cnt[left][right] = max(g_cnt[left + 1][right], g_cnt[left][right - 1]);
}
}
}
return g_cnt[0][slen - 1]; //整个字符串的最长回文长度即为所求值。
}
int main(int argc, char **argv){
//测试用字符串
const char *strings[] = {
"abxabaxbmd",
"aabbccddcbaabc",
"aa",
"aba",
"a",
"abba",
"abcba",
"xabcbam"
};
for(int i = 0; i < sizeof(strings) / sizeof(strings[0]); ++i){
fprintf(stdout, "%s\t%d\n", strings[i], dp_maxlen(strings[i]));
}
return 0;
}
|