• NOIP 2015子串(DP)


    满分做法:

    (dp[i][j][k][1/2])表示到a串的第i位置为止使用了(k)个子串匹配到b串的前j个且当前i位置选还是没选的方案数,因为当前只和(i-1)有关,所以第一维可以滚动。

    考虑转移当(a[i]==b[j])时,(dp[val][j][k][0]=(dp[val^1][j][k][0]+dp[val^1][j][k][1])%mo),因为我不选这个位置,那他一定从上一个位置就能匹配到j且用了k个子串转移过来。

    我选此位置时,(dp[val][j][k][1]=((dp[val^1][j-1][k-1][0]+dp[val^1][j-1][k][1])%mo+dp[val^1][j-1][k-1][1])%mo),因为他既可以和上一个构成同一个子串,也可以成为新的子串。

    (a[i]!=b[j])时,我选了此位置就说明我最终无法匹配,所以值为0。如果不选就和上一种情况一样。

    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int mo=1e9+7;
    int n,m,p;
    char a[1007],b[207];
    int dp[2][1007][207][2];//dp[i][j][k][1/2]表示到a串的第i位置为止使用了k个子串匹配到b串的前j个且当前i位置选还是没选的方案数,第一位可以滚动 
    int main()
    {
     scanf("%d%d%d",&n,&m,&p);
     scanf("%s",a+1);
     scanf("%s",b+1);
     dp[0][0][0][0]=1;//初值
     int val=0;
     for(int i=1;i<=n;i++)
     {
       val^=1;//奇数为1,偶数为0 
       dp[val][0][0][0]=1;
       for(int j=1;j<=min(i,m);j++)
       {
       	 for(int k=1;k<=min(j,p);k++)
       	 {
       	   if(a[i]==b[j])
    	   {
    	     dp[val][j][k][0]=(dp[val^1][j][k][0]+dp[val^1][j][k][1])%mo;
    	     dp[val][j][k][1]=((dp[val^1][j-1][k-1][0]+dp[val^1][j-1][k][1])%mo+dp[val^1][j-1][k-1][1])%mo;
           }
           else
           {
           	 dp[val][j][k][1]=0;//选了一个不匹配的点 
           	 dp[val][j][k][0]=(dp[val^1][j][k][0]+dp[val^1][j][k][1])%mo;
           }
       	 }
       }
     }
     printf("%d
    ",(dp[n&1][m][p][0]+dp[n&1][m][p][1])%mo);
     return 0;	
    }
    
  • 相关阅读:
    第三方网站实现绑定微信登陆
    安卓微信中bootstrap下拉菜单无法正常工作的解决方案
    一个Web钢琴谱记忆工具
    腾讯实习生面试经历-15年3月-Web前端岗
    AngularJS自定义指令三种scope
    AngularJS在自定义指令中传递Model
    Canvas文本绘制的浏览器差异
    AngularJS学习笔记
    善用width:auto以及white-space:nowrap以防止布局被打破
    Timeline中frame mode帧模式中idle占据大片位置
  • 原文地址:https://www.cnblogs.com/lihan123/p/11698689.html
Copyright © 2020-2023  润新知