The longest common subsequence (DP, dynamic programming)

Longest common subsequence

Title description
Give you a sequence X and another sequence Z. When all elements in Z exist in X, and the order of subscripts in X is strictly increasing, then Z is called a subsequence of X.
For example: Z=<a,b,f,c> is a subsequence of sequence X=<a,b,c,f,b,c>, the subscript sequence of elements in Z in X is <1, 2,4,6>.
Now give you two sequences X and Y. What is the length of their longest common subsequence?

Input The
input contains multiple sets of test data. Each group of input occupies one line and is two strings separated by several spaces. The length of each string does not exceed 100.

Output
For each set of inputs, output the length of the longest common subsequence of two strings.

Sample input
abcfbc abfcab
programming contest
abcd mnp

Sample output
4
2
0

Subsequence: A subset of an original sequence related to the order of the original sequence

For example: a subsequence BSY of ABCSCY

A common subsequence is a subsequence shared by two sequences, for example, ABCSCY and ABFSGP have BSY sequences

So the longest common subsequence is the longest common subsequence of the strings at both ends

Problem solving

1. Violence law

This involves permutation and combination, which is exponentially related to the length of the string

2. Dynamic programming

2.1 Find the subsequence, consider the last bit of the two subsequences

Suppose A = a1, a2, a3, a4...ax B = b1, b2, b3,...by find the longest common subsequence Lcs(x,y)=Z=z1,z2...zm; the length of Z is calculated as lcs( x,y)

(1)ax = by

Assuming the last digit ax=by=t of Ax and By, then the last digit of Z Lcs(x,y)=zm=t

Proof: (by contradiction) The last digit of Lcs(x,y) is Aa=Bb is not t, and a<x,b<y, then t can be added to the back of the common subsequence to get a longer sequence, and Hypothesis contradiction

So zm=t

With zm=t, we can get lcs(x,y) = lcs(x-1,y-1)+1 when Ax = By

(2)Ax≠By

Here let the last digit of Lcs(x,y) be t

(2.1)t≠ax,有lcs(x,y)=lcs(x-1,y)

(2.2)t≠by,有lcs(x,y)=lcs(x,y-1)

Since both cases can happen, according to the definition of the longest common subsequence lcs(x,y)=max(lcs(x-1,y),lcs(x,y-1))

(3) When Ax or By is an empty sequence, lcs(x,y)=0

So we get the following recurrence relation

lcs(x,y) =

(1)lcsx-1,y-1)+1(ax=by=t)

(2)max(lcs(x-1,y),lcs(x,y-1))(t≠ax,t≠by)

(3) 0 Ax or By is empty

After finding the recurrence relation, there are two ideas: ①Using the recursion relation to recurse, from back to forward ②Using dynamic programming, from front to back, because there are too many overlaps in the recurrence relation For example: lcs(x-1,y) includes lcs(x-1,y-1). When solving, it will be solved multiple times, resulting in increased time complexity, so here we choose to use dynamic programming from front to back Push, store the solution of the sub-problem in an array for future use, thereby reducing time complexity

From the above recurrence relation, it is easy to think of using a two-dimensional array c[m][n] to store the result of the sub-problem

The following is the recursive expression of the array

From this two-dimensional array, the length of the longest common subsequence can be easily obtained, but how to get the longest functional common subsequence itself?

By going back to the two-dimensional array, taking the picture below as an example, we can easily see the solution process of the two-dimensional array

When ax=by=t occurs, it is the oblique arrow in the figure, and the character is printed at the position where the record occurs. When the array is traversed, the longest common subsequence is also printed.

Insert picture description here

#include<stdio.h>
#include<string.h>
int f(int a,int b)
{
    
    
    if(a>=b)
    return a;
    else
    return b;
}
int main()
{
    
    
    char a[101],b[101];
    int i,x,y,j,k,n,m,l;
    while(scanf("%s%s",a,b)!=EOF)
    {
    
    
        int t=0;int d[101][101];
        x=strlen(a),y=strlen(b);
        for(i=0;i<x;i++)
        for(j=0;j<y;j++)
        d[i][j]=0;
        for(i=1;i<=x;i++)
        {
    
    
            for(j=1;j<=y;j++)
          {
    
    
               
              if(a[i-1]==b[j-1])
               d[i][j]=d[i-1][j-1]+1;
               else
               d[i][j]=f(d[i-1][j],d[i][j-1]);//这里可以用C++的max函数
          } 
         
        }
        /*for(i=1;i<=x;i++)
        {
           for(j=1;j<=y;j++)
           printf("%d ",d[i][j]);
            printf("\n");
        }*/
        printf("%d\n",d[x][y]);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_46381590/article/details/111417511