zoukankan      html  css  js  c++  java
  • 【题解】洛谷P2679 [NOIP2015TG] 子串(DP+滚动数组)

    次元传送门:洛谷P2679

    思路

    蒟蒻一开始并没有思路而去看了题解

    我们发现对于两个字串的位置 我们只需要管他们匹配成功或者匹配失败即可

    f[i][j][k] 记录当前 a[i]不论等不等于b[j] 我们可以选用也可以不选用 使用k个子串方案数(因为题目没有要求一定位置相同)

    r[i][j][k] 记录当前 a[i]==b[j] 并且我们选用a[i]和b[j] 方案数 使用k个子串方案数

    状态转移方程:

    if(A[i]==B[j])
      r[i][j][k]=(f[i-1][j-1][k-1]+r[i-1][j-1][k])%mod;
    //f[i-1][j-1][k-1] 我们把当前匹配字符单独算做一个子串
    //r[i-1][j-1][k] 我们把当前匹配字符与前面的串合并为一个子串
    
    else r[i][j][k]=0;
    //不成则为零
    
    f[i][j][k]=(r[i][j][k]+f[i-1][j][k])%mod;
    //r[i][j][k] 使用当前字符
    //f[i-1][j][k] 不使用当前字符

    因为数组并开不了辣么大

    所以我们要用到滚动数组

    把第一维该为0和1循环使用即可

    代码

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define mod 1000000007
    int n,m,K,now;
    char a[1010],b[220];
    int f[3][220][220],r[3][220][220];
    int main()
    {
        cin>>n>>m>>K;
        cin>>a+1>>b+1;
        f[0][0][0]=1;
        now=1;//滚动下标 
        for(int i=1;i<=n;i++)
        {
            f[now][0][0]=1;
            for(int j=1;j<=m;j++)
                for(int k=1;k<=K;k++)
                {
                    if(a[i]==b[j])
                    r[now][j][k]=(r[now^1][j-1][k]+f[now^1][j-1][k-1])%mod;
                    else
                    r[now][j][k]=0;
                    f[now][j][k]=(f[now^1][j][k]+r[now][j][k])%mod;
                }
            now^=1;
        }
        cout<<f[now^1][m][K];
    }
  • 相关阅读:
    最好的在线打字练习网站
    input 的 type 等于 file
    windows 删除文件或文件夹
    nvm 管理 node 版本
    github 的 fork 取消功能
    window cmd 命令行下创建文件夹和文件
    17_10_11 Redis 指令
    17_10_11 Mac 上的brew 安装指令
    17_10_11 运算符&,&&,>> 和 >>>
    17_10_10 乱码问题总结
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9881713.html
Copyright © 2011-2022 走看看