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]);
}

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