题意:
clair的字符串中有几种子序列等于bob的字符串
思路:
自前向后遍历clair的字符串( i=1;i<=l1;i++)
自后向前遍历bob的字符串( j=l2;j>=1;j–)
dp【j】代表clair前i个字符有dp【j】种子序列等于bob前j个字符
if(c[i]==b[j])dp[j]=(dp[j-1]+dp[j])%mod;
///c的第i位作为b的第j位时,前j-1个字符的选择有dp【j-1】种方法
假如clair字符串:eeettt
bob字符串:ett
比如 i=4 的时候 (此时指向clair的第一个t)
把这个t当做ett中的第二个t(j=3) clair字符串前i-1位可以拼成et的种数为0(j=2) 那么clair前i位可以拼成ett的子序列的种数增加0
把这个t当做ett中的第一个t(j=2) clair字符串前i-1位可以拼成e的种数为3(j=1) 那么clair前i位可以拼成et的子序列的种数增加3
if(c[i]==b[j]),那么dp【j】就会增加,增加的方案数是以“clair的第i位作为bob的第j位”为前提
倘若对于bob字符串自前向后遍历,
若(c[i]==b[j-1]),dp【j-1】更新,(代表“clair的第i位作为bob的第j-1位),此时若(c[i]==b[j])也成立,那么dp【j】+=dp【j-1】,此时dp【j】的方案里包含了把“clair的第i位作为bob的第j-1位”的情况,与(c[i]==b[j])成立的条件:“把clair的第i位作为bob的第j位” 冲突,所以一定要是自后向前遍历
代码:
#include<algorithm>
#include<stdio.h>
#include<string>
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
char c[5007],b[1007];
const int mod=1e9+7;
int dp[1010];
int main()
{
while(~scanf("%s",c+1))
{
scanf("%s",b+1);
int l1=strlen(c+1),l2=strlen(b+1);
//cout<<l1<<" "<<l2<<endl;
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=l1;i++)
{
for(int j=l2;j>=1;j--)
{
if(c[i]==b[j])dp[j]=(dp[j-1]+dp[j])%mod;
///c的第i位作为b的第j位时,前j-1个字符的选择有dp【j-1】种方法
}
///i只能同时与一个j匹配,则从后向前遍历
}
cout<<dp[l2]<<endl;
}
return 0;
}