题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5763
题意:给定一个串,对于该串的文本可以进行转义,即理解出第二种意思。给一个文本,求出对该文本的理解数。
做法:KMP + DP
另dp[i]表示以第i个字符结尾的意义数,则末尾不能转义时,dp[i] = dp[i - 1],可以转义时dp[i] = dp[i - 1] + dp[i - len]。在记录匹配时,需要用到KMP。
#include <cstdio>
#include <cstring>
typedef long long ll;
const int MAXN = 200000;
const int MOD = 1000000007;
char s[MAXN], t[MAXN];
int next[MAXN];
ll dp[MAXN];
bool vis[MAXN];
void KMP(){
int j;
next[0] = -1;
for(int i = 1, j = -1; s[i]; ++i){
while(j != -1 && s[i] != s[j + 1]){
j = next[j];
}
if(s[j+1] == s[i]){
j++;
}
next[i] = j;
}
for(int i = 0, j = -1; t[i]; ++i){
while(j != -1 && s[j + 1] != t[i]){
j = next[j];
}
if(s[j + 1] == t[i]){
j++;
}
if(!s[j + 1]){
vis[i] = true;
j = next[j];
}
}
return;
}
int main(){
int cas, k = 0;
scanf("%d", &cas);
while(cas--){
scanf("%s%s", t, s);
memset(vis, false, sizeof(vis));
int ml = strlen(t), l = strlen(s);
KMP();
if(vis[0]){
dp[0] = 2LL;
}else{
dp[0] = 1LL;
}
for(int i = 1; i < ml; ++i){
if(vis[i]){
if(i + 1 != l){
dp[i] = (dp[i - 1] + dp[i - l]) % MOD;
}else{
dp[i] = (dp[i - 1] + 1) % MOD;
}
}else{
dp[i] = dp[i - 1];
}
}
printf("Case #%d: ", ++k);
printf("%lld\n", dp[ml - 1]);
}
return 0;
}