編程訓練——最長公共子序列(LCS)

題目

最長公共子序列,給出兩個字符串,求出最長公共子序列的長度
比如abcd和becd,最長公共子序列是bcd,長度爲3

樣例輸入

4 4
abcd
becd

輸入爲長度分別爲4和4的字符串。

樣例輸出

3

abcd和becd的公共部分是bcd,長度爲3.

算法

用典型的動態規劃就能求解,非常簡單,不做解釋,直接看dp數組:
dp[i][j]dp[i][j]s1sis_1~s_it1tjt_1~t_j的LCS的長度,dp[0][..]dp[0][..]dp[..][0]dp[..][0]初始化都爲0,遞推式如下:
dp[i+1][j+1]={dp[i][j]+1,si+1==tj+1max(dp[i+1][j],dp[i][j+1]),otherwise dp[i+1][j+1]=\left\{ \begin{aligned} dp[i][j]+1, s_{i+1}==t_{j+1}\\ max(dp[i+1][j],dp[i][j+1]), otherwise \end{aligned} \right.

代碼

#include<stdio.h>

#define maxn 1005
#define maxm 1005

int max(int a, int b){
    return (a>b)?a:b;
}

int main(){
    int n, m;
    char s[maxn], t[maxm];
    int dp[maxn+1][maxm+1];
    while(scanf("%d %d", &n, &m)==2){
        getchar();
        for(int i = 0;i < n;i++){
            scanf("%c", s+i);
        }
        getchar();
        for(int i = 0;i < m;i++){
            scanf("%c", t+i);
        }
        for(int i = 0;i <= n;i++){
            dp[i][0] = 0;
        }
        for(int j = 0;j <= m;j++){
            dp[0][j] = 0;
        }
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= m;j++){
                if(s[i-1]==t[j-1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
            }
        }
        printf("%d\n", dp[n][m]);
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章