[vijos1982][NOIP2015]子串

Description

有两个仅包含小写英文字母的字符串\(A,B\)。现在要从字符串\(A\)中取出\(k\)个互不重叠的非空子串,然后把这\(k\)个子串按照其在字符串\(A\)中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可以使得这个新串与字符串\(B\)相等?注意:子串取出的位置不同也认为是不同的方案。

Input

第一行是三个正整数\(n,m,k\),分别表示字符串\(A\)的长度,字符串\(B\)的长度,以及问题描述中所提到的\(k\),每两个整数之间用一个空格隔开。

第二行包含一个长度为\(n\)的字符串,表示字符串\(A\)

第三行包含一个长度为\(m\)的字符串,表示字符串\(B\)

Output

输出共一行,包含一个整数,表示所求方案数。

由于答案可能很大,所以这里要求输 出答案对\(10^9+7\)取模的结果。

Sample Input

6 3 2
aabaab
aab

Sample Output

7

HINT

\(1\;\leq\;n\;\leq\;1000,1\;\leq\;m\;\leq\;200,1\;\leq\;k\;\leq\;m\).

Solution

\(f[i][j][k][0/1]\)表示\(A[1..i]\)中的\(k\)个子串与\(B[1..j]\)相等的方案数(\(0\)表示不取\(A[i]\),\(1\)表示取)

\(f[i][j][k][0]=f[i-1][j][k][0/1]\)

\(f[i][j][k][1]=f[i-1][j-1][k-1][0/1]+f[i-1][j-1][k][1](A[i]=B[j])\)

滚动数组优化空间复杂度.

#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define M 205
#define N 1005
#define K 1000000007
using namespace std;
int f[2][M][M][2],n,m,k;
char a[N],b[M];
inline void init(){
    scanf("%d%d%d%s%s",&n,&m,&k,a+1,b+1);
    f[0][0][0][0]=1;
    for(int i=1,p,q;i<=n;++i){
        p=i&1;q=p^1;
        f[p][0][0][0]=1;
        for(int j=1;j<=m;++j)
            for(int l=1;l<=k;++l){
                f[p][j][l][0]=(f[q][j][l][0]+f[q][j][l][1])%K;
                if(a[i]==b[j]) f[p][j][l][1]=((f[q][j-1][l][1]+f[q][j-1][l-1][0])%K+f[q][j-1][l-1][1])%K;
                else f[p][j][l][1]=0;
            }
    }
    printf("%d\n",(f[n&1][m][k][0]+f[n&1][m][k][1])%K);
}
int main(){
    freopen("str.in","r",stdin);
    freopen("str.out","w",stdout);
    init();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
posted @ 2016-11-20 21:56  Aireen_Ye  阅读(283)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.