📜  没有重复字符的最长公共子序列(1)

📅  最后修改于: 2023-12-03 14:56:03.031000             🧑  作者: Mango

没有重复字符的最长公共子序列

概念

在两个或多个字符串中,最长公共子序列指的是所有字符串都拥有的最长的子序列,该子序列可以不连续,但其字符在各个字符串中的相对顺序必须保持一致。

问题

现在,我们需要解决的问题是,找到两个字符串中没有重复字符的最长公共子序列。

例如,字符串S1="AGGTAB",字符串S2="GXTXAYB",则该问题的解是字符串“GTAB”。

解法

该问题可以用动态规划的方法解决。首先,我们需要用一个二维数组dp[i][j]来表示S1中前i个字符和S2中前j个字符的没有重复字符的最长公共子序列的长度。然后,我们可以用以下的递推公式来求解:

if (S1[i-1]==S2[j-1] && !used[S1[i-1]])
    dp[i][j] = 1 + dp[i-1][j-1];  
else
    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);  

其中,used[S1[i-1]]表示字符S1[i-1]是否已经被使用过,如果已经被使用,则不能被作为最长公共子序列的一部分;max函数用来求解两个长度的较大值。

最后,最长公共子序列的长度就是dp[m][n],其中m和n分别是S1和S2的长度。

实现

以下是用C++实现的代码片段:

int lcs(string s1, string s2) {
    int m = s1.length(), n = s2.length();
    int dp[m + 1][n + 1];
    memset(dp, 0, sizeof(dp));
    bool used[256] = {false};
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (s1[i - 1] == s2[j - 1] && !used[s1[i - 1]]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
                used[s1[i - 1]] = true;
            } else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
}

该函数接收两个参数,分别是字符串s1和s2,返回它们的没有重复字符的最长公共子序列的长度。