子串
题目描述
有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重
叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。
叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。
输入格式:
第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问
题描述中所提到的 k,每两个整数之间用一个空格隔开。 第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。
第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问
题描述中所提到的 k,每两个整数之间用一个空格隔开。 第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。
输出格式:
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,007 取模的结果。
样例测试点#1
输入样例:
6 3 1
aabaab
aab
输出样例:
2
样例测试点#2
输入样例:
6 3 2
aabaab
aab
输出样例:
7
7
样例测试点#3
输入样例:
6 3 3
aabaab
aab
输出样例:
7
//动态转移方程 //if(a[i]==b[j]){ // g[i][j][k]=(f[i-1][j-1][p-1]+g[i-1][j-1][q])%1000000007; // f[i][j][k]=(f[i-1][j][k]+g[i][j][k])%1000000007; // } // else{ // g[i][j][k]=0; // f[i][j][k]=f[i-1][j][k]; // } //a[i]为a中第i个字符,b[j]为b中第j个字符,k是将b中前j个字符分成k份 //(从a中取出k个等于将b分成k份); //当a[i]==b[j]时,①第i个不取有f[i-1][j][k]中情况; // ②第i个取且作为第k个部分共有 // f[i-1][j-1][k-1]+f[i-2][j-2][k-1]+f[i-3][j-3][k-1]+...+f[i-k+1][j-k+1][k-1]; //当a[i]!=b[j]时,f[i][j][k]=f[i-1][j][k];(a[i-1]与b[j]相对时的方案数); //要用滚动数组,f[][][]可以压缩到二维; #include<cstdio> int n,m,k,g[2][202][202],f[202][202]; char a[1005],b[202]; int main() { scanf("%d%d%d",&n,&m,&k); scanf("%s",a+1); scanf("%s",b+1); f[0][0]=1; for(int i=1;i<=n;i++) for(int j=m;j>0;j--) for(int q=1;q<=j;q++){ if(a[i]==b[j]){ g[i%2][j][q]=f[j-1][q-1]+g[(i-1)%2][j-1][q]; f[j][q]=f[j][q]+g[i%2][j][q]; } else{ g[i%2][j][q]=0; f[j][q]=f[j][q]; } int x=0; } printf("%d",f[m][k]); return 0; }