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 ;
    }
    
  • 相关阅读:
    创建了对嵌入的互操作程序集间接引用,无法嵌入互操作类型
    演练:Office 编程(C# 和 Visual Basic)
    【MySQL案件】ERROR 1418
    Quartus II 11.0破发点(不同的是低版本号)
    Arduino 数码管LED驱动器 阵列方法
    HDU1312 Red and Black 解读
    UVA714- Copying Books(最大最小化)
    最大流量dinci模板
    Python 实现类似PHP的strip_tags功能,并能够定义他们自己的一套保留标记
    从源代码分析modelDriven拦截器和params拦截器和拦截器prepare 和paramsPrepareParamsStack拦截器栈(让你的Struts2代码更简洁——如何培养框架设计能力
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/10802561.html
Copyright © 2011-2022 走看看