1. 程式人生 > >【NOJ1041】【DP_動態規劃】最長公共子序列

【NOJ1041】【DP_動態規劃】最長公共子序列


1041.最長公共子序列

時限:1000ms 記憶體限制:200000K  總時限:3000ms

描述

一個給定序列的子序列是在該序列中刪去若干元素後得到的序列。確切地說,若給定序列X=<x1, x2,…, xm>,則另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一個嚴格遞增的下標序列 <i1, i2,…, ik>,使得對於所有j=1,2,…,k有:

Xij = Zj

如果一個序列S即是A的子序列又是B的子序列,則稱S是A、B的公共子序列。
求A、B所有公共子序列中最長的序列的長度。

輸入

輸入共兩行,每行一個由字母和數字組成的字串,代表序列A、B。A、B的長度不超過200個字元。

輸出

一個整數,表示最長各個子序列的長度。
格式:printf("%d\n");


#include <iostream>
#include <string>

using namespace std;

string a;
string b;

int la,lb;

int dp(int i, int j);

int main()
{
    cin>>a;
    cin>>b;

    la=a.length();
    lb=b.length();

    cout<<dp(la-1, lb-1)<<endl;

    return 0;
}

int dp(int i, int j)
{
    if(i==-1||j==-1)
    {
        return 0;
    }
    else
    {
        if(a[i]==b[j])
        {
            return dp(i-1, j-1)+1;
        }
        else
        {
            return max(dp(i-1, j),dp(i, j-1));
        }
    }
}

【後記】

1.做的第一道dp題,果然如老師所說是簡單題啊……

2.話不多說,用圖說話(愛上visio了怎麼辦_(:3 」∠ )_)

如上圖所示,i 和 j 分別指向最後一個元素

當a[ i ]==b[ j ]時,證明這個元素是最長子序列的一份子,所以return dp( i-1, j-1 )+1; 

當a[ i ]!=b[ j ]時,這兩個不同的元素,每個都有可能成為最長子序列的一份子,所以return max( dp( i-1, j ), dp( i, j-1) );

上式中,max的兩個引數中,前一個是假設b[ j ]有可能成為最長子序列的一份子,而把a[ i ]去掉;後一個是假設a[ i ]有可能成為最長子序列的一份子,把b[ j ]去掉。

最後給出遞推公式叭(MathType被卸掉了在圖書館又上不了蒲公英orz,第一次嘗試LaTeX貌似還挺好用???):

dp[i,j]=\begin{matrix} dp[i-1,j-1],\ \ \ \ \ \ \ when\ a[i]==b[i] & \\ max(dp[i-1,j],dp[i,j-1]),\ \ \ \ \ \ \ else & \end{matrix}