Common Subsequence POJ - 1458(最长公共子序列)

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, x ij = 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.

Input

The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

Output

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.

Sample Input

abcfbc         abfcab
programming    contest 
abcd           mnp

Sample Output

4
2
0

 思路:

采用动态规划的方法,首先填表,L[i][j]代表字符串a的第0~i个元素,以及字符串b的0~j个元素中公共子序列的长度。显然L[0][j]和L[i][0]都为0,因为字符串a和b中总有一个字符串是长度为0的,自然不存在公共序列。当字符串a中第i个元素与字符串b中第j个元素相同时,L[i][j]=L[i-1][j-1]+1,否则,取L[i-1][j]和L[i][j-1]中的最大值。

#include <iostream>
#include<stdio.h>
using namespace std;
char a[10000];
char b[10000];
int L[10000][10000];
int la,lb;
void dp()
{
    for(int i=0; i<=la; i++)
    {
        L[i][0]=0;
    }
    for(int i=0; i<=lb; i++)
    {
        L[0][i]=0;
    }
    for(int i=1; i<=la; i++)
    {
        for(int j=1; j<=lb; j++)
        {
            if(a[i]==b[j])
            {
                L[i][j]=L[i-1][j-1]+1;
            }
            else
                L[i][j]=max(L[i][j-1],L[i-1][j]);
        }
    }
}
int main()
{
    while(scanf("%s%s",a+1,b+1)!=EOF)
    {
        la=strlen(a+1);
        lb=strlen(b+1);
        dp();
        cout<<L[la][lb]<<endl;
    }
    return 0;
}

变形

Compromise POJ - 2250

In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is not a trivial task for the countries (maybe except for Luxembourg). To enforce that Germany will fulfill the criteria, our government has so many wonderful options (raise taxes, sell stocks, revalue the gold reserves,...) that it is really hard to choose what to do. 

Therefore the German government requires a program for the following task: 
Two politicians each enter their proposal of what to do. The computer then outputs the longest common subsequence of words that occurs in both proposals. As you can see, this is a totally fair compromise (after all, a common sequence of words is something what both people have in mind). 

Your country needs this program, so your job is to write it for us.

Input

The input will contain several test cases. 
Each test case consists of two texts. Each text is given as a sequence of lower-case words, separated by whitespace, but with no punctuation. Words will be less than 30 characters long. Both texts will contain less than 100 words and will be terminated by a line containing a single '#'. 
Input is terminated by end of file.

Output

For each test case, print the longest common subsequence of words occuring in the two texts. If there is more than one such sequence, any one is acceptable. Separate the words by one blank. After the last word, output a newline character.

Sample Input

die einkommen der landwirte
sind fuer die abgeordneten ein buch mit sieben siegeln
um dem abzuhelfen
muessen dringend alle subventionsgesetze verbessert werden
#
die steuern auf vermoegen und einkommen
sollten nach meinung der abgeordneten
nachdruecklich erhoben werden
dazu muessen die kontrollbefugnisse der finanzbehoerden
dringend verbessert werden
#

Sample Output

die einkommen der abgeordneten muessen dringend verbessert werden

思路:

方法和上面那道题基本一样,只是上一题的字符变成了字符串,而且需要输出公共子序列的公共部分。所以引入了二维数组S,用来存储回溯时的访问路径。当str1[i]=str2[j]时, S[i][j]=1;L[i][j-1]>=L[i-1][j]时, S[i][j]=2;L[i][j-1]<L[i-1][j]时, S[i][j]=3。

k是最大公共子序列的长度,也就是L[l1][l2]的值,从S[l1][l2]开始向S[1][1]回溯,若S[i][j]=1,i--,j--,k--;若S[i][j]=2,j--;若S[i][j]=3,i--。

#include <iostream>
#include <stdio.h>
using namespace std;
int L[10000][10000];
int S[10000][10000];
char ans[105][1000];
char str1[105][1000];
char str2[105][1000];
int l1,l2;
void dp()
{
    for(int i=0; i<=l1; i++)
    {
        L[i][0]=0;
    }
    for(int i=0; i<=l2; i++)
    {
        L[0][i]=0;
    }
    for(int i=1; i<=l1; i++)
    {
        for(int j=1; j<=l2; j++)
        {
            if(strcmp(str1[i],str2[j])==0)
            {
                L[i][j]=L[i-1][j-1]+1;
                S[i][j]=1;
            }
            else if(L[i][j-1]>=L[i-1][j])
            {
                L[i][j]=L[i][j-1];
                S[i][j]=2;
            }
            else
            {
                L[i][j]=L[i-1][j];
                S[i][j]=3;
            }
        }
    }//填表
    int k=L[l1][l2];
    int i=l1,j=l2;
    while(i>0&&j>0)
    {
        if(S[i][j]==1)
        {
            strcpy(ans[k],str1[i]);
            k--;
            i--;
            j--;
        }
        else if(S[i][j]==2)
        {
            j--;
        }
        else i--;
    }
    for(int i=1; i<=L[l1][l2]-1; i++)
    {
        cout<<ans[i]<<" ";
     //   printf("%s ",ans[i]);

    }
    cout<<ans[L[l1][l2]]<<endl;
  //  printf("%s\n",ans[L[l1][l2]]);
}
int main()
{
    memset(str1,0,sizeof(str1));
    memset(str2,0,sizeof(str2));
    while(cin>>str1[1])
    {
        for(int i=2; ; i++)
        {
            cin>>str1[i];
            if(strcmp(str1[i],"#")==0)
            {
                l1=i-1;
                break;
            }
        }
        for(int i=1; ; i++)
        {
            cin>>str2[i];
            if(strcmp(str2[i],"#")==0)
            {
                l2=i-1;
                break;
            }
        }
        dp();

    }
    memset(str1,0,sizeof(str1));
    memset(str2,0,sizeof(str2));
    return 0;
}
发布了35 篇原创文章 · 获赞 2 · 访问量 1391

猜你喜欢

转载自blog.csdn.net/weixin_41001497/article/details/91356554