LCS算法

LCS-最长公共子序列



其实有两个概念容易模糊:

1:最长公共字串
2:最长公共子序列

最长公共子串其实是连续的字符串,而最长公共子序列只要顺序不发生改变就可以。比如abcde, hbcxdo这样两个字符串
最长公共子串是:bc
最长公共子序列是:bcd

想法:

我们可以通过动态规划的思路来思考
假设字符串Xn, Ym 然后最长公共子序列是 Zk
(n, m, k代表字符串长度)

Xn:{x1, x2, x3……xn}
Ym: {y1, y2, y3……ym}
Zk:{z1, z2, z3……zk}

LCS(Xn, Ym)= Zk
当X, Y字符串最后一个字符相等(xn==ym),那么必定符合(zk==(xn , ym))。所以我们可以简化为LCS(Xn-1, Ym-1)=Zk-1
如果xn != ym,那么Zk等于LCS(Xn-1, Ym)或者LCS(Xn, Ym-1)

实现:

使用一个二维数组dp[i][j]来记录LCS(Xi, Yj)的长度
LCS算法_第1张图片


举例:

abcde 和 hbcxdo

i 0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
2 0 0 1 1 1 1 1
3 0 0 1 2 2 2 2
4 0 0 1 2 2 3 3
5 0 0 1 2 2 3 3



代码实现:

int LCS(char s[]){
    int len = strlen(s);
    memset (dp, 0, sizeof(dp));
    for (int i = 1; i <= len; ++ i){
        for (int j = 1; j <= len; ++ j){
            if (s[i - 1] == s[len - j]) dp[i][j] = dp[i - 1][j - 1] + 1;
            else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
    }   
    return dp[len][len];
}

你可能感兴趣的:(LCS,LCS)