Timus 1577

简单DP;

状态转移方程如下:

令len[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的串的最短长度。

令res[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的最短串的方案数。

len[i][j] = str1[i]==str2[j] ? len[i-1][j-1] +1: min(len[i-1][j],len[i][j-1])+1。

若str1[i]==str2[j],res[i][j]=res[i-1][j-1];

若 str1[i]!=str2[j] ,分三种情况:

(1)len[i-1][j] < len[i][j-1] , res[i][j]=res[i-1][j];

(2)len[i-1][j] > len[i][j-1],  res[i][j]=res[i][j-1];

(3)len[i-1][j]==len[i][j-1],  res[i][j]=res[i][j-1]+res[i-1][j];

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

#define MAX 1000000007

char str1[2010],str2[2010];

int res[2][2010][2];

int work(int n,int m)

{

    int i,j,e=0;

    for(i=0;i<=m;i++)

    {

        res[e][i][0]=i;  res[e][i][1]=1;

    }

    for(i=1;i<=n;i++)

    {

        e=1-e;

        res[e][0][0]=i;  res[e][0][1]=1;

        for(j=1;j<=m;j++)

        {

                     if(str1[i]==str2[j])

             {

                 res[e][j][0]=res[1-e][j-1][0]+1;

                 res[e][j][1]=res[1-e][j-1][1];

                 continue;

             }

             if(res[e][j-1][0] < res[1-e][j][0])

             {

                 res[e][j][0]=res[e][j-1][0]+1;

                 res[e][j][1]=res[e][j-1][1];

             }

             if(res[e][j-1][0] > res[1-e][j][0])

             {

                 res[e][j][0]=res[1-e][j][0]+1;

                 res[e][j][1]=res[1-e][j][1];

             }

                     if(res[e][j-1][0] == res[1-e][j][0])

             {

                 res[e][j][0]=res[e][j-1][0]+1;

                 res[e][j][1]=(res[e][j-1][1]+res[1-e][j][1])%MAX;

             }

        }

    }

    return res[e][m][1];

}

int main()

{

    while(scanf("%s %s",str1+1,str2+1)!=EOF)

    {

        printf("%d\n",work(strlen(str1+1),strlen(str2+1)));

    }

    return 0;

}

你可能感兴趣的:(IM)