1. 程式人生 > 實用技巧 >D - Common Subsequence

D - Common Subsequence

求兩個字串的最長公共序列,輸出這個序列的長度。

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

Input

abcfbc abfcab
programming contest 
abcd mnp

Output

4
2
0

列如:abcfbc abfcab

F[i][j]=F[i-1][j-1]+1;(a[i]==b[j])

F[i][j]=max(F[i-1][j],F[i][j-1])(a[i]!=b[j]);

n由於F(i,j)只和F(i-1,j-1), F(i-1,j)和F(i,j-1)有關, 而在計算F(i,j)時, 只要選擇一個合適的順序, 就可以保證這三項都已經計算出來了, 這樣就可以計算出F(i,j). 這樣一直推到f(len(a),len(b))就得到所要求的解了.

LCS演算法:

  1、序列str1和序列str2

    ·長度分別為m和n;
    ·建立1個二維陣列L[m.n];
    ·初始化L陣列內容為0
    ·m和n分別從0開始,m++,n++迴圈:
    - 如果str1[m] == str2[n],則L[m,n] = L[m - 1, n -1] + 1;
    - 如果str1[m] != str2[n],則L[m,n] = max{L[m,n - 1],L[m - 1, n]}
    ·最後從L[m,n]中的數字一定是最大的,且這個數字就是最長公共子序列的長度
    ·從陣列L中找出一個最長的公共子序列。

  2、從陣列L中查詢一個最長的公共子序列

    i和j分別從m,n開始,遞減迴圈直到i = 0,j = 0。其中,m和n分別為兩個串的長度。
    ·如果str1[i] == str2[j],則將str[i]字元插入到子序列內,i–,j–;
    ·如果str1[i] != str[j],則比較L[i,j-1]與L[i-1,j],L[i,j-1]大,則j–,否則i–;(如果相等,則任選一個)

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[1001][1001];
char s1[1001],s2[1001];
int main()
{
    while(~scanf("%s %s",s1,s2))
    {
        int l1=strlen(s1);
        int l2=strlen(s2);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=l1;i++)
        {
            for(int j=1;j<=l2;j++)
            {
                if(s1[i-1]==s2[j-1])
                dp[i][j]=dp[i-1][j-1]+1;
                else
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
        printf("%d\n",dp[l1][l2]);
    }
}