CF432Dプレフィックスとサフィックス
問題の意味
あなたは長さnの長い文字列を与え、「完璧なストリングは、」その接頭語の両方はまた、数は数の長い文字列で「完璧なストリング」と統計サブ文字列を求めてそのサフィックスをされて表示されます
分析
ネックスは、配列を見つけ、NEXから得られた各プレフィックスが表示された回数[n]はラインを下ります
実際には、この質問市、KMPは、テンプレートを発生する質問の各プレフィックス番号を求めます
プレフィックス番号が書かれた要求を表示されます
for(int i = 1 ; i <= n ; ++i) num[i]++;
for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
この手段は、まず全てのiプレフィックス長の、1である、独自の大あり
長い接頭辞を考慮して、私はへの遷移の数でそれを置くことができますか?接頭辞自体算出したが、計算は次の接頭辞自体限りではない、NEX [I]は、彼の最長の共通接頭辞と接尾辞、すなわち右端点のI、NEX長[i]と接頭サブストリングであります同じことが、私は何度も、NEXが登場[i]にもプレフィックス番号を追加する必要があります彼が登場しました
for(int i = 1 ; i <= n ; ++i) num[nex[i]]++;
for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
for(int i = 1 ; i <= n ; ++i) num[i]++;
この手段は、最初に自分自身を除外して、最終的に追加します。
短い個人的な勧告の最初の良い理解、
この質問のコードでは
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5+100;
int n;
int nex[N] , num[N] , cnt[N];
char c[N];
int main()
{
scanf("%s",c+1); n = strlen(c+1);
for(int i = 2 , k = 0 ; i <= n ; ++i)
{
while(k && c[i] != c[k + 1]) k = nex[k];
if(c[i] == c[k + 1]) k++; nex[i] = k;
}
int tot = 0 , k = nex[n];
while(k) cnt[++tot] = k , k = nex[k];
printf("%d\n" , tot + 1);
// for(int i = 1 ; i <= n ; ++i) num[i]++;
// for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
for(int i = 1 ; i <= n ; ++i) num[nex[i]]++;
for(int i = n ; i >= 1 ; --i) num[nex[i]] += num[i];
for(int i = 1 ; i <= n ; ++i) num[i]++;
for(int i = tot ; i >= 1 ; --i)
printf("%d %d\n" , cnt[i] , num[cnt[i]]);
printf("%d 1\n" , n);
return 0;
}