您的位置:首页 > 其它

HDU 5282 Senior's String DP(LCS变形)

2017-10-12 10:53 627 查看
HDU 5282

题意:给出两个字符串a,b.假如a,b的LCS长度为L,从a中选出子序列长度为LCS并且该子序列在b中出现,问有多少种方案? 

| a|,|b|<=1e3. (长度为L的子序列有2^L个).两个子序列有某个位置选择的下标不同就视为个不同.

dp[i][j]:a的前缀i和b的前缀j的LCS长度.

f[i][j]:a的前缀i有多少个长度为dp[i][j]的子序列出现在b的前缀j中.

然后现在考虑选不选a的第i个字符.

不选a[i],则需要dp[i-1][j]=dp[i][j].

选a[i],则此时的LCS最后一个字符为a[i] 找到b的前缀j中字符a[i]最后一次出现的位置p
则如果选a[i] 则要满足dp[i-1][p-1]+1=dp[i][j].

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,inf=0x3f3f3f3f;
const ll mod=1e9+7;
char a
,b
;
ll dp

,f

;
int last[27];
int main()
{
int T;
cin>>T;
while(T--)
{
memset(f,0,sizeof(f));
memset(dp,0,sizeof(dp));
scanf("%s%s",a+1,b+1);
int n=strlen(a+1),m=strlen(b+1);
f[0][0]=1;
for(int j=1;j<=m;j++)
f[0][j]=1;
for(int i=1;i<=n;i++)
{
f[i][0]=1;
memset(last,-1,sizeof(last));
for(int j=1;j<=m;j++)
{
last[b[j]-'a']=j;
if(a[i]==b[j])
dp[i][j]=dp[i-1][j-1]+1;
dp[i][j]=max(dp[i][j],max(dp[i-1][j],dp[i][j-1]));

if(dp[i-1][j]==dp[i][j])
f[i][j]=f[i-1][j];
int p=last[a[i]-'a'];
if(p!=-1)
{
if(dp[i-1][p-1]+1==dp[i][j])
f[i][j]=(f[i][j]+f[i-1][p-1])%mod;
}
}
}

printf("%lld\n",f
[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: