最长公共子序列加强版------dp题解与感悟dp

      字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列,使得对所有的j=0,1,…,k-1,有xij = yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
对给定的两个字符序列,求出他们最长的公共子序列。
输入格式 Input Format    
     第1行为第1个字符序列,都是大写字母组成,以”.”结束。长度小于5000。
     第2行为第2个字符序列,都是大写字母组成,以”.”结束,长度小于5000。
输出格式 Output Format    
     第1行输出上述两个最长公共子序列的长度。
     第2行输出所有可能出现的最长公共子序列个数,答案可能很大,只要将答案对100,000,000求余即可。

输入 :ABCBDAB。输出:  4    时间:1s
            BACBBD.                 7
     这道题很明显有两问,求最长公共子序列,这个的状态转移方程不过就是f[i][j]=max(f[i][j],f[i-1][j]) | |f[i][j]=max(f[i][j],f[i][j-1]) | |

然后就是if(ch[i]==ch[j])f[i][j]=max(f[i][j],f[i-1][j-1]+1);;;;而另一问就比较偏了,这里是求最长公共子序列的个数,显然只要能转化为最优答案的途径都是一种这里只要构建一个DAG就好了,可我也不知道则么建,于是只知道从前往后把状态全部便利只要能转换成最优的答案就累加,应该是加法原理。。。准确一点用一个数组来记录f数组所有的变化只要不是最优解初值不附就好了,于是可以有g[0][i]=1,g[j][0]=1,这是附初值,然后转移具体代码如下,lzx学长正解加一点自己理解。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
char h;
char ch[5100],ch1[5100];
int len=0,len1=0;
int f[5100][5100],g[5100][5100];
const int mod=(int)1e8;
int main()
{
    //freopen("1.in","r",stdin);
    while(1)
    {
        cin>>h;
        if(h=='.')
            break;
        ch[++len]=h;
    }
    while(1)
    {
        cin>>h;
        if(h=='.')
            break;
        ch1[++len1]=h;
    }
    for(int i=0;i<=len;i++)g[i][0]=1;
    for(int j=0;j<=len1;j++)g[0][j]=1;
    for(int i=1;i<=len;i++)
        for(int j=1;j<=len1;j++)
        {
            if(ch[i]==ch1[j])
                f[i][j]=max(f[i][j],f[i-1][j-1]+1);
            f[i][j]=max(f[i][j],f[i-1][j]);
            f[i][j]=max(f[i][j],f[i][j-1]);
            if(f[i][j]==f[i-1][j])
                (g[i][j]+=g[i-1][j])%=mod;
            if(f[i][j]==f[i][j-1])
                (g[i][j]+=g[i][j-1])%=mod;
            if(ch[i]==ch1[j])
            {
                if(f[i][j]==f[i-1][j-1]+1)
                    (g[i][j]+=g[i-1][j-1])%=mod;
            }
            else if(f[i][j]==f[i-1][j-1])(g[i][j]-=g[i-1][j-1])%=mod;
        }
    cout<     cout<<(g[len][len1]+mod)%mod<     return 0;
}

从这道题中感觉dp还是如渊如狱,如山如岳,好了 清静怜清影。

你可能感兴趣的:(dp,好难)