hdu3336(kmp)

来源:互联网 发布:婚庆后期软件 编辑:程序博客网 时间:2024/05/16 06:41

题目大意:

给定一个字符串s,求s的每个前缀在此字符串中出现的次数,然后对次数求和,然后再对10007取模,就是要输出的答案。

思路:

刚开始也许会想,枚举前缀,求出每个前缀出现的次数,但这样效率太低。

利用kmp算法的next数组可以很好的解决这个问题,    next数组存放的是字符串的前缀和后缀能匹配的字符个数的最大值。

对于i,(1 <= i <=n),n是字符串s的长度

        如果next[i]  == 0,则表示   由s的前i个字符组成的字符串的所有后缀肯定和其前缀不匹配。

        否则      由s的前i个字符组成的字符串存在某个前缀和后缀匹配的情况,也就是该前缀的出现的次数应该加上1。

       定义f[i]为  在由s的前i个字符组成的字符串subs中,subs所有前缀出现的次数之和。答案也就是f[n];

f[i] = f[i-1] + 1 + (next[i]==0?0:1)

在我的程序中没有用f数组,直接用的是ans

hdu3336AC代码:

#include <cstdio>#include <cstring>const int maxn = 200005;char p[maxn];int n;int next[maxn];void getnext(char* p){    next[1] = 0;    int k = 0;    for(int i=2;i<=n;i++)    {        while(k!=0 && p[k+1] != p[i])            k = next[k];        if(p[k+1] == p[i]) k++;        next[i] = k;    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        scanf("%s",p+1);        getnext(p);        int ans = n % 10007;        for(int i=1;i<=n;i++)        {            ans = (ans + (next[i]==0?0:1)) % 10007;        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击