hdu3336(kmp)

題目大意:

給定一個字符串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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章