📜  最长回文子序列的C程序| DP-12(1)

📅  最后修改于: 2023-12-03 15:40:17.114000             🧑  作者: Mango

最长回文子序列的C程序 | DP-12

最长回文子序列是指一个序列从左到右与从右到左相同的序列中,长度最长的那个序列。例如,序列“ABA”和“AAA”都是回文子序列,“ABC”不是回文子序列。

动态规划是求解最长回文子序列问题的常用方法。下面我们来看一下C语言的实现。

思路

我们在DP-11中已经介绍了求解最长回文子串的动态规划方法,而求解最长回文子序列的动态规划方法有些不同。设P(i, j)为字符串s[i..j]的最长回文子序列,则当i=j时,P(i, j)=1;当s[i]=s[j]时,P(i, j)=P(i+1, j-1)+2;否则,P(i, j)=max(P(i+1, j), P(i, j-1))。最终的答案即为P(0, n-1),其中n为字符串s的长度。

代码实现

下面是C语言的实现代码:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1000

/**
 * 计算最长回文子序列的长度
 * @param s 字符串
 * @return 最长回文子序列的长度
 */
int longest_palindrome_subseq(char *s) {
    int n = strlen(s);
    int dp[MAX_LEN][MAX_LEN];
    memset(dp, 0, sizeof(dp));

    for (int i = 0; i < n; i++) {
        dp[i][i] = 1;
    }

    for (int len = 2; len <= n; len++) {
        for (int i = 0; i < n - len + 1; i++) {
            int j = i + len - 1;
            if (s[i] == s[j]) {
                dp[i][j] = dp[i + 1][j - 1] + 2;
            } else {
                dp[i][j] = (dp[i + 1][j] > dp[i][j - 1]) ? dp[i + 1][j] : dp[i][j - 1];
            }
        }
    }

    return dp[0][n - 1];
}

/**
 * 测试最长回文子序列函数
 */
void test_longest_palindrome_subseq() {
    char s[] = "BBABCBCAB";
    int ans = longest_palindrome_subseq(s);
    printf("%d\n", ans); // 输出5
}

int main() {
    test_longest_palindrome_subseq();
    return 0;
}

我们先定义了最大字符串长度为1000(MAX_LEN)。然后我们实现了一个longest_palindrome_subseq函数用于计算最长回文子序列长度。该函数首先计算出字符串s的长度n,然后定义dp数组用于存储最长回文子序列的长度。由于长度为1的子序列必定是回文子序列,所以我们先对dp[i][i]赋值为1。之后,我们使用两重循环计算dp数组。

最终,我们返回dp[0][n-1],即字符串s的最长回文子序列长度。

最后,我们实现了一个test_longest_palindrome_subseq函数来测试我们的实现。在该函数中,我们传入一个字符串s,并计算其最长回文子序列长度。这里我们使用了字符串“BBABCBCAB”进行测试,结果输出5,符合预期。

总结

这就是求解最长回文子序列的动态规划方法。当我们计算出dp数组后,即可得到字符串的最长回文子序列。这个算法在字符串处理、语音识别、生物学等领域中有着广泛的应用。