説明
N文字(各文字が97と126の間でASCIIコードを持っている、包括的)で指定された文字列Sの各プレフィックスのために、我々は接頭辞が定期的に文字列であるかどうかを知りたいです。すなわちごとに、あるI(2 <= iが= Nを<)、我々は長さSの接頭辞iはAKのように書くことができるように(もしあれば)最大K> 1を知りたい、それが連結Kであります時間は、もちろんいくつかの文字列Aに、我々はまた、期間Kを知りたいです
入力
入力はいくつかのテストケースで構成されています。各テストケースは、二つのラインで構成されています。最初のものはNを含み(2 <= N <= 1 000 000) - S.The第二行は、入力ファイルは行で終わる文字列Sを含む文字列の大きさを有する
その上に数ゼロ。
出力
各テストケースは、出力「テストケース番号」と一行に連続テストケース番号の、次に、各プレフィクスの長さIは、周期K> 1、出力I及び期間Kは、単一のスペースで区切られたプレフィックスのサイズを有します。プレフィックスサイズは昇順でなければなりません。各テストケースの後に空白行を印刷します。
サンプル入力
3
aaa
12
aabaabaabaab
0
サンプル出力
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4
タイトル効果:文字列入力、出力及び添字I長N、I前の文字列は、N個の同一の列に分割することができます
思考:KMPアルゴリズムGETNEXT操作、同一の各々は、最大プレフィクスとインデックス列に対応する接尾語長を表すことができ、彼の前に、障害が特定の時間と一致する場合に二つの文字列の一致をスキップすることができるように、しかし、この質問は彼が十分にGETNEXTした後、我々は唯一の配列の値を知る必要があり、操作が一致する必要はありません。私たちは最初から横断しているので、そのたびに私は - の値NXTは、[i]は、サイクル長さ== 0%の合計の長さは、それはそれはリサイクルすることができることを示す場合には、ループの長さは、その問題ですが、話題彼は、あなたが「A」を入力すると、正しい答えは何も出力する必要がありますが、あなたはメソッドを押すだけのようになります。ループの長さは1とみなされていない場合> 1 Kが、それは、アナロジーであります出力11、別の例では、あなたが「ABCD」と入力すると、正しい答えも出力されていないものにならなければならないが、彼は、出力「11、21、31、41、」私たちは条件を追加することになるでしょう!その理由は、すでに理解していれば(間違った文字は、ループの単一セクションとして扱われ置くが、そこには他の単一文字のプレフィックスをされていないと同じような状況をサフィックスた場合、彼のNXT値が0である、それは、最初の場所にJ復帰をさせていることですKMPは、ここで述べた)、その後KMP説明^ _ ^の他の首長を見て、読むことができるはずです理解していません
各サンプルは空白行を持った後〜、出力形式ことに注意してください
PS:限られた言語標準。。。KMPはまだ理解していない場合、あなたはこの質問を書いてみることができただろう。http://poj.org/problem?id=2406
この質問は唯一POJ2406サイクルです。
ACコード:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 5;
char str[maxn];
int nxt[maxn], n, X;
void getnext() {
nxt[0] = -1;
int i = 0, j = -1;
while (i < n) {
if (j == -1 || str[i] == str[j])
nxt[++i] = ++j;
else
j = nxt[j];
}
}
int main()
{
while (scanf("%d", &n) && n) {
memset(nxt, 0, sizeof(nxt));
scanf("%s", str);
getnext();
cout << "Test case #" << ++X << endl;
for (int i = 1; i <= n; i++) {
if (i % (i - nxt[i]) == 0 && i != (i - nxt[i])) //防止单个字符作为循环体
cout << i << " " << i / (i - nxt[i]) << endl;
}
cout << endl;
}
return 0;
}