zoukankan      html  css  js  c++  java
  • 【洛谷P2679】子串

    题目

    题目链接:https://www.luogu.com.cn/problem/P2679
    有两个仅包含小写英文字母的字符串 \(A\)\(B\)

    现在要从字符串 \(A\) 中取出 \(k\) 个互不重叠的非空子串,然后把这 \(k\) 个子串按照其在字符串 \(A\) 中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 \(B\) 相等?

    注意:子串取出的位置不同也认为是不同的方案。

    思路

    \(f[i][j][k][0/1]\) 表示 \(A\) 串前 \(i\) 个位置,匹配了 \(k\) 次匹配到 \(B\) 串前 \(j\) 位,其中第 \(i\) 位选或不选的方案数。
    那么显然有

    \[f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1] \]

    \[f[i][j][k][1]=f[i-1][j-1][k-1][0]+f[i-1][j-1][k-1][1]+f[i-1][j-1][k][1] \]

    发现空间过不了,将 \(i\) 这一位滚动一下即可。
    时间复杂度 \(O(nmk)\),空间复杂度 \(O(mk)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1010,M=210,MOD=1000000007;
    int n,m,t,f[2][M][M][2];
    char a[N],b[M];
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&t);
    	scanf("%s%s",a+1,b+1);
    	f[0][0][0][0]=1;
    	for (int i=1;i<=n;i++)
    	{
    		int id=i&1;
    		memset(f[id],0,sizeof(f[id]));
    		for (int j=0;j<=m;j++)
    			for (int k=0;k<=t;k++)
    			{
    				f[id][j][k][0]=(f[id^1][j][k][0]+f[id^1][j][k][1])%MOD;
    				if (j && a[i]==b[j])
    				{
    					if (k) f[id][j][k][1]=(f[id^1][j-1][k-1][0]+f[id^1][j-1][k-1][1])%MOD;
    					f[id][j][k][1]=(f[id][j][k][1]+f[id^1][j-1][k][1])%MOD;
    				}
    			}
    	}
    	printf("%d",(f[n&1][m][t][0]+f[n&1][m][t][1])%MOD);
    	return 0;
    }
    
  • 相关阅读:
    POJ1112 Team Them Up!
    WebSocket相关介绍
    长轮询 & 短轮询
    图片上传 & 预览
    sessionStorage & localStorage & cookie & session
    进程 & 线程
    https介绍与讲解
    http请求
    TCP/IP的连接与断开
    浏览器缓存
  • 原文地址:https://www.cnblogs.com/stoorz/p/13714188.html
Copyright © 2011-2022 走看看