問題:給定字符串,求其最長回文子串的長度。回文串是形如”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;
}