序列型动态规划之最长公共子序列(LCS)

先上状态转移方程,还是很容易看明白的

例题是Codevs的1862,这个题不是实现了方程就可以了的,还要完成一个事情那就是计数,数一数到底有多少个最长公共子序列

 1 #include<cstdio>
 2 #include<cstring> 
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=5005;
 6 const int p=1e8;
 7 char a[maxn],b[maxn];
 8 int dp[maxn][maxn],f[maxn][maxn];
 9 int main()
10 {
11     scanf("%s%s",a+1,b+1);
12     int al=strlen(a+1)-1;
13     int bl=strlen(b+1)-1;
14     for(int i=0;i<=al;i++) f[i][0]=1;
15     for(int i=0;i<=bl;i++) f[0][i]=1;
16     for(int i=1;i<=al;i++)
17         for(int j=1;j<=bl;j++)
18         {
19             if(a[i]==b[j])
20             {
21                 dp[i][j]=dp[i-1][j-1]+1;
22                 int k1=0,k2=0;
23                 if(dp[i][j]==dp[i-1][j]) k1=1;
24                 if(dp[i][j]==dp[i][j-1]) k2=1;
25                 f[i][j]=f[i-1][j-1]+(k1*f[i-1][j])+(k2*f[i][j-1]);
26                 f[i][j]=(f[i][j]+p)%p;
27             }
28             else
29             {
30                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
31                 int k1=0,k2=0,k3=0;
32                 if(dp[i][j]==dp[i-1][j]) k1=1;
33                 if(dp[i][j]==dp[i][j-1]) k2=1;
34                 if(dp[i][j]==dp[i-1][j-1]) k3=1;
35                 f[i][j]=(k1*f[i-1][j])+(k2*f[i][j-1])-(k3*f[i-1][j-1]);
36                 f[i][j]=(f[i][j]+p)%p;
37             }
38         }
39     printf("%d\n%d\n",dp[al][bl],f[al][bl]);
40     return 0;
41 }

在这里我们用dp记录长度,用f记录个数

由于输入是以“.”结尾的,所以读入的时候有些许的变化

    scanf("%s%s",a+1,b+1);
    int al=strlen(a+1)-1;
    int bl=strlen(b+1)-1;

这样读入的时候真正的字符串的下标是从a+1开始的,循环的时候从1开始循环,到strlen(a+1)结束

因为结尾字符不属于串,所以给al--就好了

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9473114.html