1. 程式人生 > >dp-最長公共子序列

dp-最長公共子序列

 

 

最長公共子序列(NYOJ36)

時間限制: 3000 ms  |  記憶體限制:65535 KB 難度: 3  
描述
咱們就不拐彎抹角了,如題,需要你做的就是寫一個程式,得出最長公共子序列。
tip:最長公共子序列也稱作最長公共子串(不要求連續),英文縮寫為LCS(Longest Common Subsequence)。其定義是,一個序列 S ,如果分別是兩個或多個已知序列的子序列,且是所有符合此條件序列中最長的,則 S 稱為已知序列的最長公共子序列。
 
輸入
第一行給出一個整數N(0<N<100)表示待測資料組數
接下來每組資料兩行,分別為待測的兩組字串。每個字串長度不大於1000.
輸出
每組測試資料輸出一個整數,表示最長公共子序列長度。每組結果佔一行。
樣例輸入
2
asdf
adfsd
123abc
abc123abc
樣例輸出
3
6

分析:dp基礎題目。用一個二維陣列 dp[i][j] 存放每次狀態的最長公共子序列長度,陣列下標i,j是當前已經比較的兩個字串長度。兩個字串 s1s2s3s4...si 和 t1t2t3t4...tj ,每比較一個字元,都可能會使最長公共子序列的長度變大。

s1s2s3s4...si s(i+1)和t1t2t3t4...tj t (j+1)的公共子序列可能是:

(1) s1s2s3s4...si 和 t1t2t3t4...tj末尾加上一個相同的字元,即s(i+1)=t (j+1)

(2) s1s2s3s4...si 和 t1t2t3t4...tj t (j+1)的公共子序列

(3) s1s2s3s4...si s(i+1) 和 t1t2t3t4...tj 的公共子序列

由此可以推出公式

dp[i+1][j+1]=max( dp[i+1][j],dp[i][j+1] );

dp[i+1][j+1]=dp[i][j]+1;

AC程式碼:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

char s1[1005],s2[1005];
int dp[1005][1005];
int len1,len2;

int main()
{
    int t;
    scanf("%d",&t);
    getchar();
    while(t--)
    {
        memset(dp,0,sizeof(dp));///每次都要清0
        gets(s1);
        gets(s2);
        len1=strlen(s1);
        len2=strlen(s2);
        for(int i=0;i<len1;i++)
        {
            for(int j=0;j<len2;j++)
            {
                if(s1[i]==s2[j])
                    dp[i+1][j+1]=dp[i][j]+1;///當i=j=0並且字元相等時,dp[1][1]中的1代表兩個字串比較的字元個數
                else
                    dp[i+1][j+1]=max( dp[i+1][j],dp[i][j+1] );
            }
        }
        printf("%d\n",dp[len1][len2]);
    }
    return 0;
}
View Code