首页 > 其他 > 详细

【洛谷2679】子串(动态规划)

时间:2018-11-10 23:36:20      阅读:165      评论:0      收藏:0      [点我收藏+]

点此看题面

大致题意: 让你从一个字符串中选择\(k\)个互不重叠的非空子串,使其按序拼接恰好组成另一个给定的字符串,求方案数。


动态规划

比较显然,这可以用动态规划解决。

考虑用\(f_{i,j,t,s}\)表示在第一个字符串前\(i\)位中选择\(t\)个子串组成第二个字符串前\(j\)位,且选/不选(1/0)第\(i\)的方案数,并用\(g_{i,j,t}\)记录\(f_{i,j,t,0}+f_{i,j,t,1}\)

则不难得出\(f_{i,j,t,0}=g_{i-1,j,t}\)

而对于\(f_{i,j,t,1}\)的转移,就需要分类讨论了:

\(s1_i!=s2_j\),显然该位不能选,故\(f_{i,j,t,1}=0\)

\(s1_i==s2_j\),则有两种情况:新选一个子串或不新选一个子串。即\(f_{i,j,t,1}=f_{i-1,j-1,t,1}+g_{i-1,j-1,t-1}\)

大致思路就是如此简单。


关于内存

等等,数组好像开不下?

\(hl666\)奆佬说:“滚存不就好了吗!”

于是这题就做完了。


代码

#include<bits/stdc++.h>
#define N 1000
#define M 200
#define XRY 1000000007
#define Inc(x,y) ((x+=(y))>=XRY&&(x-=XRY))
using namespace std;
inline int GetSum(int x,int y) {return Inc(x,y),x;}
int n,m,k,f[2][M+5][M+5][2],g[2][M+5][M+5];char s1[N+5],s2[M+5];
int main()
{
    register int i,j,t;
    scanf("%d%d%d%s%s",&n,&m,&k,s1,s2),g[0][0][0]=g[1][0][0]=f[0][0][0][0]=f[1][0][0][0]=1;//读入+初始化
    for(i=1;i<=n;++i) for(j=1;j<=m;++j) for(t=1;t<=k;++t)
    {
        f[i&1][j][t][0]=g[(i&1)^1][j][t],//转移f[i][j][t][0]
        f[i&1][j][t][1]=s1[i-1]^s2[j-1]?0:GetSum(f[(i&1)^1][j-1][t][1],g[(i&1)^1][j-1][t-1]),//转移f[i][j][t][1]
        g[i&1][j][t]=GetSum(f[i&1][j][t][0],f[i&1][j][t][1]);//计算g[i][j][t]
    }
    return printf("%d",g[n&1][m][k]),0;//输出答案
} 

【洛谷2679】子串(动态规划)

原文:https://www.cnblogs.com/chenxiaoran666/p/Luogu2679.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!