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

    问题描述

    有两个仅包含小写英文字母的字符串 A 和 B。

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

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

    输入格式

    第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问题描述中所提到的 k,每两个整数之间用一个空格隔开。

    第二行包含一个长度为 n 的字符串,表示字符串 A。

    第三行包含一个长度为 m 的字符串,表示字符串 B。

    输出格式

    输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,007 取模的结果。

    样例输入

    #1

    6 3 1
    aabaab
    aab

    #2

    6 3 2
    aabaab
    aab

    #3

    6 3 3
    aabaab
    aab

    样例输出

    #1

    2

    #2

    7

    #3

    7

    数据范围

    题解

    K个子串互不重叠,但是是可以相连的,也就是说,一个长度为2的子串,可以看成两个长度为1的子串相连。

    f[i][j][k][0/1]表示A的前i个字符选出k个子串得到B的前j个字符,其中,0表示A[i]不选,1表示A[i]要选。

    当A[i]==B[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]+f[i-1][j-1][k-1][1]+f[i-1][j-1][k-1][0]

    当A[i]!=B[i]时

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

    f[i][j][k][1]=0

     

    (上面方程看懂的自动跳过这段)

    **********************************************************************************************************

    当A[i]==B[i]时

    如果A[i]不选,那么B[j]必定从A的前i-1个字符中取,方案数为前i-1个字符选和不选的总和,即f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

    如果A[i]选,如果A[i-1]选,A[i]可以选择接在上一个子串的后面,或者自己作为下一个子串的第一个字符,如果A[i-1]不选,显然A[i]只能作为下一个子串的第一个字符,以上三种方案加起来,就是选A[i]的方案数,即f[i][j][k][1]=f[i-1][j-1][k][1]+f[i-1][j-1][k-1][1]+f[i-1][j-1][k-1][0]

     

    当A[i]!=B[i]时

    如果A[i]不选,情况同上,f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]

    由于A[i]!=B[i],A[i]选不了,f[i][j][k][1]=0

    **********************************************************************************************************

    考虑数组的大小,要开到1000×200×200×2=8×107,而通常开两三个1×107的数组就面临MTE的风险了。

    注意到f[i]只和f[i-1]有关,于是滚动数组压掉一维。

     1 #include <cstring>
     2 #include <cstdio>
     3 const int maxn=1e9+7;
     4 int n,m,K,f[2][205][205][2];
     5 char a[1005],b[205];
     6 int main()
     7 {
     8     int i,j,k;
     9     scanf("%d%d%d",&n,&m,&K);
    10     scanf("%s",a+1);
    11     scanf("%s",b+1);
    12     f[1][0][0][0]=f[0][0][0][0]=1;
    13     for (i=1;i<=n;i++)
    14       for (j=1;j<=m;j++)
    15         for (k=1;k<=K;k++)
    16           if (a[i]==b[j])
    17             f[i&1][j][k][0]=(f[(i-1)&1][j][k][0]+f[(i-1)&1][j][k][1])%maxn,
    18             f[i&1][j][k][1]=(1ll*f[(i-1)&1][j-1][k][1]+f[(i-1)&1][j-1][k-1][1]+f[(i-1)&1][j-1][k-1][0])%maxn;
    19           else
    20             f[i&1][j][k][0]=(f[(i-1)&1][j][k][0]+f[(i-1)&1][j][k][1])%maxn,
    21             f[i&1][j][k][1]=0;  
    22     printf("%d",(f[n&1][m][K][0]+f[n&1][m][K][1])%maxn);
    23     return 0;
    24 }
  • 相关阅读:
    第19章_枚举:
    第14章_类型信息:
    第13章_字符串:
    纯css背景图自适应
    事务隔离机制_悲观锁_乐观锁
    hibernate 缓存
    list 和 iterate
    hibernate 性能优化之 1+N 问题
    QBC(Query By Criteria) QBE (Query By Example)
    HQL(Hibernate Query Language)
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9817263.html
Copyright © 2011-2022 走看看