题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5791
题目解释:求公共子序列,给你连个串,可以不连续取,但必须按照顺序取子序列
思路:类似于求最大公共子序列,如果a[i]=b[j],dp[i][j]=dp[i-1][i]+dp[i][j-1]+dp[i-1][j-1]-2dp[i-1][j-1]+1+dp[i-1][j-1] 即考虑
a[i]!=b[j] ,dp[i][j]=dp[i-1][i]+dp[i][j-1]+dp[i-1][j-1]-2dp[i-1][j-1]
dp[i-1][i]+dp[i][j-1]+dp[i-1][j-1]-2dp[i-1][j-1]表示的是当不把a[i]和b[j]相不相等考虑进去而统计的全部子序列和,当相等时可以就单取a[i]和b[j](+1的原因)。也可以考虑将a[i]和b[j]加入子序列中,就是在dp[i-1][j-1]这个集合中加入a[i]和b[j],就有dp[i-1][j-1]个子序列
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define mod 1000000007
using namespace std;
long long dp[2][1005];//压缩,减少空间
int a[1005];
int b[1005];
long long sum;
int main()
{
int m,n;
while(~scanf("%d %d",&n,&m))
{
sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
{
scanf("%d",&b[i]);
for(int j=1;j<=n;j++)
{
dp[i%2][j]=(dp[(i+1)%2][j]+dp[(i)%2][j-1]-dp[(i+1)%2][j-1]+mod)%mod;
if(a[j]==b[i])
{
dp[i%2][j]=dp[i%2][j]+dp[(i-1)%2][j-1]+1;
}
}
}
printf("%lld\n",dp[m%2][n]);
}
return 0;
}