Vijos[1982]NOIP2015Day2T2 子串 substring 動態規劃
阿新 • • 發佈:2017-07-28
bsp 得到 mat main tar cstring font () 鏈接
第三行包含一個長度為 m 的字符串,表示字符串 B。
【輸出格式】
輸出文件名為 substring.out。
輸出共一行,包含一個整數,表示所求方案數。 由於答案可能很大,所以這裏要求對輸出答案對 1,000,000,007 取模 的結果。
【輸入輸出樣例 1】
substring.in
6 3 1
aabaab
aab
substring.out
2
【輸入輸出樣例 2】
substring.in
6 3 2
aabaab
aab
substring.out
7
【輸入輸出樣例 3】
substring.in
6 3 3
aabaab
aab
substring.out
7
那麽,對於Σ可以用前綴和優化,這樣的時間就可以卡進去了,但是空間還是要炸,所以我們采用滾動數組來優化空間即可。詳見代碼。
子串 (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
6 3 1
aabaab
aab
substring.out
2
【輸入輸出樣例 2】
substring.in
6 3 2
aabaab
aab
substring.out
7
【輸入輸出樣例 3】
substring.in
6 3 3
aabaab
aab
substring.out
7
【題解】
NOIP2015Day2T2
一道好好的DP題
我們用dp[i][j][k]表示在B串中匹配i個,在A串中匹配到的位置為j,共使用k個子串的方案總數,則dp[i][j][k]=Σdp[i-1][j‘][k-1] +dp[i-1][j-1][k]
那麽,對於Σ可以用前綴和優化,這樣的時間就可以卡進去了,但是空間還是要炸,所以我們采用滾動數組來優化空間即可。詳見代碼。
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=1000+5,M=200+5;
const int mod=1e9+7;
char s1[N],s2[M];
int n,m,K;
int dp[2][N][M],sum[2 ][N][M];
//dp[i][j][k]=Σdp[i-1][j‘][k-1](1<=j‘<=j-1) +dp[i-1][j-1][k]
int main(){
scanf("%d%d%d%s%s",&n,&m,&K,s1+1,s2+1);
memset(dp,0,sizeof dp);
memset(sum,0,sizeof sum);
int I=0,J=1;
for (int i=1;i<=n;i++){
if (s2[1]==s1[i])
dp[0][i][1]=1;
sum[0][i][1]=sum[0][i-1][1]+dp[0][i][1];
}
for (int i=2;i<=m;i++,I^=1,J^=1){
memset(dp[J],0,sizeof dp[J]);
memset(sum[J],0,sizeof sum[J]);
for (int j=1;j<=n;j++){
if (s2[i]!=s1[j])
continue;
for (int k=1;k<=K;k++)
if (j>=2)
dp[J][j][k]=(sum[I][j-1][k-1]+dp[I][j-1][k])%mod;
else
dp[J][j][k]=dp[I][j-1][k];
}
for (int k=1;k<=K;k++)
for (int j=1;j<=n;j++)
sum[J][j][k]=(sum[J][j-1][k]+dp[J][j][k])%mod;
}
printf("%d",sum[I][n][K]);
return 0;
}
Vijos[1982]NOIP2015Day2T2 子串 substring 動態規劃