P2679 子串

题意:现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 B 相等?

   注意:子串取出的位置不同也认为是不同的方案。

 

 

输入输出样例

输入样例#1:
6 3 1 
aabaab 
aab
输出样例#1: 
2
输入样例#2: 
6 3 2 
aabaab 
aab
输出样例#2: 
7
输入样例#3: 
6 3 3 
aabaab 
aab
输出样例#3: 
7

说明

正解:DP

  设f[i][j][0/1]表示分成i个字串,当前在A的k(循环),B串在j(倒着枚举滚动),1:用当前i,2:总的方案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
using namespace std;
#define int long long
const int mod=1000000007LL;
inline int read()
{
    int f=1,x=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            f=-f;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;    
}
inline void put(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        put(x/10);
    putchar(x%10+'0');
}
inline void in()
{
    freopen("substring.in","r",stdin);
    freopen("substring.out","w",stdout);
}
inline void out()
{
    fclose(stdin);
    fclose(stdout);
}
int f[250][250][2];
int n;
int m;
int k;
char a[1050];
char b[250];
inline void DPstart()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=1;j--)
        {
            for(int p=1;p<=k;p++)
            {
                if(a[i]!=b[j])    //用i但i不与b相等,所以不合法,方案=0
                    f[p][j][1]=0;
                else
                {
                    if(p==1&&j==1)     //边界
                    {
                        f[p][j][1]=1;    //用当前的匹配一个,所以为1
                        f[p][j][0]++;    //相当于+=f[p][j][1];总方案
                        f[p][j][0]%=mod;  //别忘取模
                    }
                    else
                    {
                        (f[p][j][1]=f[p-1][j-1][0])%=mod;   //当前取,且单分
                        (f[p][j][0]+=f[p][j][1])%=mod;      //累加方案
                        if(i>=2)
                        {
                            if(a[i-1]==b[j-1])    //上一个也相同
                            {
                                (f[p][j][0]+=f[p][j-1][1])%=mod;   //可以拼接把当前与上一个连起来的情况
                                (f[p][j][1]+=f[p][j-1][1])%=mod;   //上一个和这个都取
                            }        
                        }
                        
                    }
                }    
            }
        }
    }
}
signed main()
{
//    in();
    n=read();
    m=read();
    k=read();
    scanf("%s",a+1);
    scanf("%s",b+1);
    DPstart();
    put(f[k][m][0]%mod);
    out();
    return 0;
}

 

  

posted @ 2018-09-03 11:14  olinr  阅读(165)  评论(0编辑  收藏  举报