POJ1458(最长公共子序列)

来源:互联网 发布:mac双系统修改默认启动 编辑:程序博客网 时间:2024/06/05 21:58
考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质:


(1) 如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列;


(2) 如果am-1!=bn-1,则若zk-1!=am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列;


(3) 如果am-1!=bn-1,则若zk-1!=bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。


这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1!=bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。


dp方程:
如果a[i]=a[j] 则dp[i][j]=dp[i-1][j-1]+1
否则dp[i][j]=max(dp[i-1][j],dp[i][j-1])

AC代码:

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>#define N 1005using namespace std;char a[N], b[N];int dp[N][N];int main(){    while(~scanf("%s %s", a, b)){        getchar();        int la = strlen(a);        int lb = strlen(b);        dp[0][0] = 0;        for(int i =1; i<=la; i++) dp[i][0] = 0;        for(int i =1; i<=lb; i++) dp[0][i] = 0;        for(int i =1; i<=la; i++){            for(int j =1; j<=lb; j++){                if(a[i-1]==b[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[la][lb]);    }    return 0;}


0 0
原创粉丝点击