[机房练习赛4.7] 深意 KMP

来源:互联网 发布:ubuntu ntfs 移动硬盘 编辑:程序博客网 时间:2024/05/01 07:45

深意(meaning.in/meaning.out)

有的词语常常别有深意,比如hehe可以单纯的表示hehe,也可以表示“excuse me?!”,现给出一段话s,和一个单词t,已知单词t有别有深意,也就是说有两个意思,求s可能有多少个意思?答案对1000000007取模。
【输入格式】
第一行一个数n,表示测试的组数。
接下来n组,每组两行,表示s和t。
【输出格式】
一共n行,第i行表示第i组的s个意思个数。
5
【输入样例】
4
hehehe
hehe
woquxizaolehehe
woquxizaole
hehehehe
hehe
woyaoqugenbierenliaotianle
wanan
【输出样例】
3
2
5
1
【样例解释】
黑色表示取原意,红色表示取深意。
第1组: hehehe, hehehe, hehehe
第3组: hehehehe, hehehehe, hehehehe, hehehehe, hehehehe
【数据规模】
50% 数据满足 len(s),len(t) ≤ 1000。
100% 数据满足len(t) ≤ len(s) ≤ 100000, n ≤ 10。
s和t仅包含小写字母。
【解法】
KMP+DP
设dp[i]为s长度为i的前缀,有多少种意思,初始情况dp[0]=1。
一般情况下dp[i] = dp[i-1]
如果在s中找到一个t,则t会为s带来新的意思,即是说dp[i] = dp[i-1] + dp[I – lent]。最后输出dp[lens]即可。
如果暴力找出所有t,应该可以得到50分。
我们使用KMP算法快速找到所有s中的t,就可以通过本题。

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int mod = 1000000000 + 7;const int N = 100000 + 5;int T;char s[N],t[N];int next[N],dp[N];void getgo(){    int i = 0,j = -1;    int len = strlen(t);    next[0] = -1;    while( i < len ){        if( j == -1 || t[i] == t[j] ){            i++;j++;            next[i] = j;        } else j = next[j];    }}void calculate(){    int i = 0,j = 0;    int len1 = strlen(s); int len2 = strlen(t);    while( i < len1 ){        if( j == -1 || s[i] == t[j] ){            i++;j++;            dp[i] = dp[i-1];            if( j == len2 ){                dp[i] = (dp[i] + dp[i-j]) % mod;                j = next[j];            }        } else j = next[j];    }}int main(){    freopen("meaning.in","r",stdin);    freopen("meaning.out","w",stdout);    scanf("%d", &T);    while(T--){        scanf("%s", s);scanf("%s", t);        getgo();        dp[0] = 1;        calculate();        int len = strlen(s);        printf("%d\n",dp[len]);    }    return 0;}
0 0
原创粉丝点击