トピックへのリンク: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;
}
後で戻ってそれを変更するには、別のタイトルから簡単な方法を感じた場合、私は、複雑ではないと思うかわかりません