noip 2015 T5 子串 字符串dp




2

.子串

 

(substring.cpp/c/pas) 

【问题描述】

 

有两个仅包含小写英文字母的字符串

A

B

现在要从字符串

A

中取出

k

互不重

的非空子串,

然后把这

k

个子串按照其在字符串

A

中出现的顺序依次连接起来得到一

个新的字符串,

请问有多少种方案可以使得这个新串与字符串

B

相等?注意:

子串取出

的位置不同也认为是不同的方案

 

 

【输入格式】

 

输入文件名为

substring.in

 

第一行是三个正整数

n

m

k

,分别表示字符串

A

的长度,字符串

B

的长度,以及问

题描述中所提到的

k

,每两个整数之间用一个空格隔开。

 

第二行包含一个长度为

n

的字符串,表示字符串

A

 

第三行包含一个长度为

m

的字符串,表示字符串

B

 

【输出格式】

 

输出文件名为

substring.out

 

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

由于答案可能很大,所以这里要求输

出答案对

1,000,000,007

取模的结果。

 

 

【输入输出样例

1

 

substring.in 

substring.out 

6 3 1 

aabaab 

aab 

 

 

见选手目录下

substring/substring1.in

substring/substring1.ans

 

 

【输入输出样例

2

 

substring.in 

substring.out 

6 3 2 

aabaab 

aab 

 

 

见选手目录下

substring/substring2.in

substring/substring2.ans

 

 

【输入输出样例

3

 

substring.in 

substring.out 

6 3 3 

aabaab 

aab 

 

 

见选手目录下

substring/substring3.in

substring/substring3.ans

 

 



 

【输入输出样例说明】

 

所有合法方案如下:

(加下划线的部分表示取出的子串)

 

样例

1

aab 

aab / aab 

aab

 

样例

2

a ab 

aab / 

aba 

ab

 / a 

ba 

ab 

/ aab 

a ab

 

aa b 

aab / 

aa 

baa 

b

 / aab 

aa b

 

样例

3

a a b

 aab / 

a a 

baa 

b

 / 

a

 ab 

a

 a 

b

 / 

a

 aba 

a

 

b

  

a

 b 

a

 a 

b

 / a 

a

 ba 

a

 

b

 / aab 

a

 

a

 

b

 

 

【输入输出样例

4

 

见选手目录下

substring/substring4.in

substring/substring4.ans

 

 

【数据规模与约定】

 

对于第

1

组数据:

1

n

500

1

m

50

k=1

 

对于第

2

组至第

3

组数据:

1

n

500

1

m

50

k=2

 

对于第

4

组至第

5

组数据:

1

n

500

1

m

50

k=m

 

对于第

1

组至第

7

组数据:

1

n

500

1

m

50

1

k

m

 

对于第

1

组至第

9

组数据:

1

n

1000

1

m

100

1

k

m

 

对于所有

10

组数据:

1

n

1000

1

m

200

1

k

m

题解:这道dp题和树形dp的有一个思想很像,考虑当前这一位能否延续到后面用0/1表示,也就是说dp【i】【j】【k】【0/1】表示A串前i位B串前j位用了k部分,不能/能往后延续。用滚动数组优化空间。
#include<cstdio>
#include<cstring>
const int mod=1000000007;
int dp[2][210][210][2];
char a[1010],b[210];
int main()
{
    int i,j,k,m,n,l,p,q,x,y,z;
    scanf("%d%d%d",&n,&m,&l);
    scanf("%s",a+1);
    scanf("%s",b+1);
    dp[0][0][0][0]=dp[1][0][0][0]=1;
    for (i=1;i<=n;i++)
    {
        for (j=1;j<=m;j++)
           for (k=1;k<=l;k++)
           {
                dp[i&1][j][k][0]=dp[i&1^1][j][k][0];
                if (a[i]==b[j])
                {
                    dp[i&1][j][k][1]=(dp[i&1^1][j-1][k][1]+dp[i&1^1][j-1][k-1][0])%mod;
                    dp[i&1][j][k][0]=(dp[i&1][j][k][0]+dp[i&1][j][k][1])%mod;
                }
            }
        for (j=1;j<=m;j++)
           for (k=1;k<=l;k++)
             dp[i&1^1][j][k][0]=dp[i&1^1][j][k][1]=0;
    }
    printf("%d\n",dp[n&1][m][l][0]);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章