[HDOJ5763]Another Meaning(KMP, DP)

时间:2023-11-18 12:56:26

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5763

题意:给定两个字符串a和b,其中a中的字符串如果含有子串b,那么那部分可以被替换成*。问有多少种替换方法。

kmp求出b在a中完全匹配后的结尾位置,然后dp(i)表示匹配到i时替换的方案数(不替换也算一次方案)。首先更新dp(i)=dp(i-1),当且仅当i点是一个完全匹配的终点时,加上dp(i-nb)处的值。

 #include <bits/stdc++.h>
using namespace std; const int maxn = ;
const int mod = ;
int na, nb;
char a[maxn];
char b[maxn];
int pre[maxn];
bool vis[maxn];
int dp[maxn]; void getpre(char *b, int *pre) {
int j, k;
pre[] = -;
j = ;
k = -;
while(j < nb) {
if(k == - || b[j] == b[k]) {
j++;
k++;
pre[j] = k;
if(b[j] != b[k]) pre[j] = k;
else pre[j] = pre[k];
}
else k = pre[k];
}
} void kmp() {
int i = ;
int j = ;
getpre(b, pre);
while(i < na) {
if(j == - || a[i] == b[j]) {
i++; j++;
}
else j = pre[j];
if(j == nb) vis[i] = ;
}
} int main() {
// freopen("in", "r", stdin);
int T, _ = ;
scanf("%d", &T);
while(T--) {
printf("Case #%d: ", _++);
scanf("%s %s", a, b);
memset(vis, , sizeof(vis));
memset(dp, , sizeof(dp));
na = strlen(a); nb = strlen(b);
kmp(); dp[] = ;
for(int i = ; i <= na; i++) {
dp[i] = dp[i-];
if(vis[i]) {
dp[i] += dp[i-nb];
dp[i] %= mod;
}
}
printf("%d\n", dp[na]%mod);
}
return ;
}