zoukankan      html  css  js  c++  java
  • LOJ2424 NOIP2015 子串 【DP】*

    LOJ2424 NOIP2015 子串


    LINK


    题目大意是给你两个序列,在a序列中选出k段不重叠的子串组成b序列,问方案数

    首先我们不考虑相邻的两段,把所有相邻段当成一段进行计算

    然后设dpi,j,k,0/1表示a使用了i为,b匹配到j位,一共有k段,当前这一位选不选的方案数

    然后转移显然:
    dpi,j,k,0=dpi−1,j,k,0+dpi−1,j,k,1
    dpi,j,k,1=dpi−1,j−1,k,1+dpi−1,j−1,k−1,0(条件ai=bja_i=b_jai=bj)
    然后之后的dp就非常显然了

    把i滚动数组掉就可以了

    然后注意数组清零和j和k的枚举下界是0。。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int Mod=1e9+7;
     4 const int N=1e3+10,M=2e2+10;
     5 #define fu(a,b,c) for(int a=b;a<=c;a++)
     6 int dp[2][M][M][2];
     7 int c[N][N];
     8 int n,m,k,ind=0;
     9 char a[N],b[N];
    10 int add(int a,int b){return (a+b)%Mod;}
    11 int mul(int a,int b){return 1ll*a*b%Mod;}
    12 void init() {
    13   fu(i,0,n)c[i][0]=1;
    14   fu(i,1,n)fu(j,1,i)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
    15 }
    16 int main() {
    17   scanf("%d%d%d",&n,&m,&k);
    18   scanf("%s%s",a+1,b+1);
    19   init();
    20   dp[ind][0][0][0]=1;
    21   fu(i,1,n) {
    22     ind^=1;
    23     memset(dp[ind],0,sizeof(dp[ind]));
    24     fu(j,0,min(i,m))
    25       fu(k,0,j) {
    26         dp[ind][j][k][0]=add(dp[ind^1][j][k][0],dp[ind^1][j][k][1]);
    27         if(k==0||j==0||a[i]!=b[j])continue;
    28         dp[ind][j][k][1]=add(dp[ind^1][j-1][k][1],dp[ind^1][j-1][k-1][0]);
    29       }
    30   }
    31   int ans=0;
    32   fu(i,1,k)ans=add(ans,mul(add(dp[ind][m][i][0],dp[ind][m][i][1]),c[m-i][k-i]));
    33   printf("%d",ans);
    34   return 0;
    35 }
  • 相关阅读:
    坐标系的冷知识2
    坐标系的冷知识
    XMPP即时通讯(代码实现)
    约束问题
    实现ios屏幕的横竖屏自适应
    3D Touch ? 木有6s,也阔以玩!!!
    Autolayout
    Xcode7免证书真机调试
    微信支付
    二维码扫描
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676256.html
Copyright © 2011-2022 走看看