zoukankan      html  css  js  c++  java
  • 2015提高组 子串

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

    一个整数,表示所求方案数。

    由于答案可能很大,所以这里要求输出答案对 10000000071000000007 取模的结果。


    lv神Day6T2,一个爆水的dp,呃,然而净顾着写T1,还忘了删注释

    首先dp方程是好推的,dp[i][j][l][0]代表主串到i,模式串到j,分了l段,当前位可取也可不取

    dp[i][j][l][1]代表主串到i,模式串到j,分了l段,当前位必须取

    dp[i][j][l][1]=dp[i-1][j-1][l][1]+dp[i-1][j-1][l-1][0]

    dp[i][j][l][0]=dp[i][j][l][1]+dp[i-1][j][l][0]

    然后就发现MLE了,怎么解决呢?

    我们将这个dp数组看做一个网格图

    每一个dp[i][j][l][0],都是从他的左上角和他的上方的两个方格处转移过来的

    所以我们将循环倒过来,这样就可以压缩我们的状态,提前计算出要处理的方格的上面的方格,再从前面的方格转移

    如下:
    dp[j][l][1]=dp[j-1][l][1]+dp[j-1][l-1][0]

    dp[j][l][0]=dp[j][l][1]+dp[j][l][0]

    然后就是基础操作

    下面给出代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    inline int rd(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int dp[1006][206][2];
    char a[100006];
    char b[100006];
    int n,m,k;
    int mod=1000000007;
    int main(){
        n=rd();
        m=rd();
        k=rd();
        scanf("%s%s",a+1,b+1);
        dp[0][0][0]=1;
        for(int i=1;i<=n;i++){
            for(int j=m;j>=1;j--){
                if(a[i]==b[j]){
                    for(int v=k;v>=1;v--){
                        dp[j][v][1]=(dp[j-1][v-1][0]+dp[j-1][v][1])%mod;
                        dp[j][v][0]=(dp[j][v][1]+dp[j][v][0])%mod;
                    }
                }
                else for(int v=1;v<=k;v++) dp[j][v][1]=0;
            }
        }
        printf("%d",dp[m][k][0]);
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    Java日志框架Slf4j+Log4j入门
    Pandas常用函数入门
    Noip2018 倒计时
    【缩点】洛谷P3387
    用Visio进行数据库建模、设计和实现
    SQL Server 教程
    MS TransactSQL 存储过程的解密算法
    泛型编程
    网络实现语音
    Visual C++ 例程下载
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9715303.html
Copyright © 2011-2022 走看看