HDU 3336(KMP)の文字列をカウント

トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=3336

問題解決のアイデア:

まず、元のアレイ構成のミスマッチ配列

[i]は最長共通接尾辞の前に0〜I-1を表し、失敗

まず、我々シリングANS = lenは、各プレフィックス自体を追加する最初のものです

私たちは、そうでない場合は、プレフィックスと呼ばれ、接尾辞配列失敗で得られたものと一致しないことを保証することができます。

次トラバーサルは、[2]〜[LEN]をフェイル

私たちのそれぞれのサフィックスサフィックスの最後に全てのi-1を見つけることができません

まず、現在は失敗[i]が0でない場合、0〜X == I-1-X〜I-1がなければなりません

そして、我々は、I-1の前に接尾辞で終わるていなかったので、何の接尾辞が以前、数えなかったことを確認してください

我々は、すべての行う方法の-1 I接尾辞を取得したい、0より大きいから証明することができ、0より大きい[i]は、[失敗]失敗し、不一致の側面に沿って戻って見ることであるI-1-X〜I-この値がゼロより大きくないまで[i]は] [失敗[失敗]失敗見て、より短い伸長の終了時に1 I-1を切り出します。

コード:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 10007

using namespace std;

const int N = 2e5+5;

char s[N];
int fail[N];

void kmp(int len)
{
    fail[0] = -1;
    for (int i=0,j=-1;i<len;){
        if (j==-1||s[i]==s[j]){
            i++;j++;
            fail[i] = j;
        }
        else j = fail[j];
    }

    int ans = len%mod;
    for (int i=2;i<=len;i++){
        if (fail[i]>0) ans++;
        int now = fail[i];
        while (fail[now]>0){
            ans++;
            now = fail[now];
        }
    }
    printf("%d\n",ans%mod);
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--){
        int n;
        scanf("%d",&n);
        scanf("%s",s);
        kmp(n);
    }
    return 0;
}

後で戻ってそれを変更するには、別のタイトルから簡単な方法を感じた場合、私は、複雑ではないと思うかわかりません

おすすめ

転載: blog.csdn.net/weixin_43768644/article/details/94546846