首页 > 其他 > 详细

洛谷P2679 子串

时间:2019-05-02 16:56:56      阅读:163      评论:0      收藏:0      [点我收藏+]

传送门

分析:

首先发现,为了保证无后效性的一位一位往后推,我们需要记录当前推到 $ 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\ne 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(n\cdot 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\n" , (f[n & 1][m][k][0] + f[n & 1][m][k][1]) % mod) ;
    return 0 ;
}

洛谷P2679 子串

原文:https://www.cnblogs.com/Stephen-F/p/10802561.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!