当前位置: 首页>>算法&结构>>正文


DP求最大回文子串长度

问题:给定字符串,求其最长回文子串的长度。回文串是形如”aba”, “abba”的对称字符串。例如:字符串“xabcbam”的最长回文字符串长度为5。

这个问题可以用动态规划(DP)来求解,其初始状态和转移方程如下:

gif.latex-8实现的代码如下:


#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;
}
本文由《纯净天空》出品。文章地址: https://vimsky.com/article/991.html,未经允许,请勿转载。