[DP][NOIP2015]子串
子串
題目描述
有兩個僅包含小寫英文字母的字符串 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 取模 的結果。
樣例輸入
6 3 1
aabaab
aab
樣例輸出
2
提示
題解:
從網上ctrl c + v來的你們不會介意的對吧(逃~
“*那麽記一下思路吧,這道題是要壓縮的,它會卡空間的,要滾動數組。
我們按照三維的來考慮,我們再記一個數組f[i][j][k]為選擇第i位後的a串前i個b串前j個選擇k個子串有幾種組合方式
s[i][j][k]是a串前i個b串前j個選擇k個子串有幾種組合方式,f,s數組的差別是一個選了第i個,一個不一定選了第i個
f數組的遞推思路:要是a的第i位能夠和b的第j位匹配上,我們選擇第i位當一個串是一種情況,
這個時候我們把s數組的s[i-1][j-1][k-1]轉移過來就可以了,那麽i-1顯然也要和j-1匹配上才能多加上額外的一些情況,
如果i-1和j-1都匹配不上就不能再往左延伸了,所以如果a[i]!=b[j]相當於一個公共子串被切斷一樣,f[i][j][k]=0
所以:
f[i][j][k]=f[i-1][j-1][k]+s[i-1][j-1][k-1] (a[i]==b[j])
f[i][j][k]=0 (a[i]!=b[j])
s數組的遞推思路:當a[i]==b[j]時,我們可以選i也可以不選,我們加上f數組就好了和不選的情況s[i-1][j][k]就可以了,
s[i][j][k]=f[i][j][k]+s[i-1][j][k]
壓縮的思路:由於我們的每次i都只與i-1有關,所以我們可以把第一維壓縮掉,因為後面的j要用到j-1的情況,
所以我們從後往前更新,k同理,也是從後往前,然後要控制範圍是min(K,j)*”
代碼:
1 #include<algorithm> 2 #include<cstdio> 3 4 int n, m, k; 5 long long f[2][205][205], s[2][205][205]; 6 char a[1005], b[205]; 7 const int mod = 1000000007; 8 9 int read(){ 10 int x = 0, f = 1; 11 char ch = getchar(); 12 while (ch < ‘0‘ || ch > ‘9‘) { 13 if (ch == ‘-‘) { 14 f = -1; 15 } 16 ch = getchar(); 17 } 18 while (ch >= ‘0‘ && ch <= ‘9‘) { 19 x = x * 10 + ch - ‘0‘; 20 ch = getchar(); 21 } 22 return x * f; 23 } 24 25 int main(){ 26 n = read(); 27 m = read(); 28 k = read(); 29 scanf("%s", a + 1); 30 scanf("%s", b + 1); 31 int now = 1, last = 0; 32 f[0][0][0] = 1; 33 for (int i = 1; i <= n; i++) { 34 f[now][0][0] = 1; 35 for (int j = 1; j <= m; j++) { 36 for (int kk = 1; kk <= k; kk++) { 37 if (a[i] == b[j]) { 38 s[now][j][kk] = (s[last][j - 1][kk] + f[last][j - 1][kk - 1]) % mod; 39 } 40 else { 41 s[now][j][kk] = 0; 42 } 43 f[now][j][kk] = (f[last][j][kk] + s[now][j][kk]) % mod; 44 } 45 } 46 std::swap(now, last); 47 } 48 printf("%lld\n", f[last][m][k]); 49 return 0; 50 }
[DP][NOIP2015]子串