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

    传送门

    分析:

    首先发现,为了保证无后效性的一位一位往后推,我们需要记录当前推到 $ a $ 串的哪一个位置了;接着还有记录匹配了 $ b $ 串的那几个字符。因为是按照原串顺序,所以相当于是即匹配 $ b $ 串的前几个字符。有这些还不够,我们还要记录划分了几个子串。最后,为了便于转移,我们还要标记一维 $ 0/1 $ 状态,表示 $ a $ 串中的第 $ i $ 个字符是否选入。

    这样,我们就设计好了状态。我们记 $ f_{i,j,p,v} $ 表示到 $ a $ 串的第 $ i $ 个位置为止使用 $ p $ 个子串匹配 $ b $ 串前 $ j $ 位字符且第 $ i $ 个位置选或不选 $ (v) $ 的方案数。

    我们分情况考虑:

    $ 1. $ 当 $ a_i=b_j $ 时:

    ①$ f_{i,j,p,0} $ :由于这位不选,所以就是前面一位选和不选方案数之和,即 $ f_{i,j,p,0}=f_{i-1,j,p,0}+f_{i-1,j,p,1} $ 。

    ② $ f_{i,j,p,1}=f_{i-1,j-1,p,1}+f_{i-1,j-1,p-1,0}+f_{i-1,j-1,p-1,1} $ 。

    $ 2 . $ 当 $ a_i e b_j $ 时:

    ①不选情况同上,即 $ f_{i,j,p,0}=f_{i-1,j,p,0}+f_{i-1,j,p,1} $ 。

    ②由于选不了,自然就是 $ 0 $ ,即 $ f_{i,j,p,1}=0 $ 。

    观察转移方程,发现每次转移只用到了前一位!于是我们把第一维很愉快地滚掉了。这样,空间复杂度就保证是 $ O(mk) $ 了。那么时间呢?时间是 $ O(ncdot mk) $ ,但是时间不像空间,这个复杂度是可以接受的。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    #define re register
    #define mod 1000000007
    using namespace std ;
    const int maxn = 1005 ;
    const int maxm = 210 ; 
    
    int n , m , k ;
    char a[maxn] , b[maxm] ;
    bool val = true ;
    int f[2][maxm][maxm][2] ;
    //f[i][j][p][v]:表示a串的第i个位置为止使用p个子串匹配b串的前j位字符且第i个位置选还是不选(v)的方案数
     
    inline void dp() {
    	f[0][0][0][0] = f[1][0][0][0] = 1 ;
    	for(re int i = 1 ; i <= n ; ++ i , val ^= 1) 
    		for(re int j = 1 ; j <= m ; ++ j) 
    			for(re int p = 1 ; p <= k ; ++ p) {
    				if(a[i] == b[j]) {
    					f[val][j][p][0] = (f[val ^ 1][j][p][0] + f[val ^ 1][j][p][1]) % mod ;
    					f[val][j][p][1] = (f[val ^ 1][j - 1][p][1] + (f[val ^ 1][j - 1][p - 1][0] + f[val ^ 1][j - 1][p - 1][1]) % mod) % mod ;
    				}
    				else {
    					f[val][j][p][0] = (f[val ^ 1][j][p][0] + f[val ^ 1][j][p][1]) % mod ;
    					f[val][j][p][1] = 0 ;
    				}
    			}
    }
    
    int main () {
    	scanf("%d%d%d" , &n , &m , &k) ;
    	scanf("%s%s" , a + 1 , b + 1) ;
    	dp() ;
    	printf("%d
    " , (f[n & 1][m][k][0] + f[n & 1][m][k][1]) % mod) ;
    	return 0 ;
    }
    
  • 相关阅读:
    QDUOJ 来自xjy的签到题(bfs+状压dp)
    HDU
    【原创+整理】线程同步之详解自旋锁
    【原创】浅说windows下的中断请求级IRQL
    【原创】驱动开发中Memory read error导致的蓝屏问题
    [转&精]IO_STACK_LOCATION与IRP的一点笔记
    【原创】《windows驱动开发技术详解》第4章实验总结二
    【原创】《windows驱动开发技术详解》第4章实验总结一
    【转载】LINUX 和 WINDOWS 内核的区别
    【原创】Windows服务管家婆之Service Control Manager
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/10802561.html
Copyright © 2011-2022 走看看