- 天河c线性dp时空优化
子串
- 2025-4-2 13:31:35 @
#include<iostream>
using namespace std;
int n,m,k;
char a[1145],b[228];//ab串
int dp[2][205][205][2],r;//考虑递推永远只用前一组,直接滚动数组,留一个暂存
const int mod=1000000007;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
for(int i=1;i<=n;i++){//遍历a,取出字符
dp[r][0][0][0]=1;//什么也不做也是一种,边界很关键,递推会用到
r=(r+1)%2;//滚动
for(int j=1;j<=m;j++){//遍历b,匹配字符
for(int s=1;s<=k;s++){//不同的子串数,递推
if(a[i]==b[j]) {
dp[r][j][s][1]=(dp[(r+1)%2][j-1][s][1]+(dp[(r+1)%2][j-1][s-1][1]+dp[(r+1)%2][j-1][s-1][0])%mod)%mod;//只要相加了就要mod,否则有爆的风险
}//(r+1)%2就是前一组,这里要分类讨论,即选上这个字符后是断开自成新串还是连着上一个串,由于都要选所以前面都是[(r+1)%2][j-1]
//如果是连着上一个串说明s的个数不变,实际数量完全等同于dp[(r+1)%2][j-1][s][1]
//如果是断开自成新串说明到了这里s的数量加了1,那么上一个是s-1
//由于上一个无论选没选不影响断开,所以加上上一个的选或不选,即为dp[(r+1)%2][j-1][s-1][1]+dp[(r+1)%2][j-1][s-1][0]
else{
dp[r][j][s][1]=0;
}//字符不匹配没得选,0
dp[r][j][s][0]=(dp[(r+1)%2][j][s][0]+dp[(r+1)%2][j][s][1])%mod;
//这个不选?说明b的字符数(j)没变,把前一组选和不选的都加起来
}
}
}
cout<<(dp[r][m][k][0]+dp[r][m][k][1])%mod;//最后一个可以选或不选,都要加
return 0;
}
0 comments
No comments so far...