接尾辞配列&ツリー&オートマトン
シリーズサフィックス文字列構造の概要
一部のブロガーの習慣
ストリングと呼ばれる\(S \)と呼ばれる長さ(N \)\、文字列\(bは\)に結合(A + B \)\、開始インデックスから、S_ {I、Jの(\ } \)を表し\(Iを\)に\(J \)ストリング片の
文字列の間に\(<、> \)辞書式比較を表します
問題解決のすべての例は、テキストの最後に見つけることができます
\ [\ \]
\ [\ \]
1:SA(接尾辞配列)
必要アレイ\(RK [I]は、\)を表し\(I \) 、接尾辞順位(同一の非存在下)\(SA [I] \)は、ランクを表しを\(I \)接尾番号、及び補助アレイ\(CNT、TMP \)
1-1接尾辞ソート
ブロガーのレベルが十分ではない、私はDC3(学ぶために行かなかったようなので\(O(N)\) )のアルゴリズムをDA(下に提示される\(O(\ N- N-ログ)\) )のアルゴリズム
サフィックスは、定義により、選別することである\(S \)各サフィックス(\ \ {N- I} S_の)(以下、\(Suf_i \)辞書式に最小のヌル文字をソート辞書式によれば、)
乗算器は基数ソート+実装を検討
現在の長さのために決定されている\(K \) 、すなわち、(S_ {I、I + \ K-1} \) 次を考慮しなければ、ソート(過剰ヌル文字)が完了した(S_ {I、I \ + 2K-1} \)順序
(S_うち{I、I + 2K- 1} S_のS_ {I、I + K-1} +の= {I + K、I + 2K- 1} \)\を、それがためにソート完成部品の値に応じて可能です基数ソート与えるための2つのパーツの組合せ使用\(2K \)を
あなたは基本ケースの下のプロセスのこの種に精通していない場合、我々は、高速で行を達成することができます
次のようにプロセスがあります
根据首字母初始化sa,rk数组
for(k=1;k<=n;k<<=1) {
rep(i,1,n) tmp[i]=i;
sort(...);
求出sa,rk,注意当前相同的串的rk也要相同
}
コードの実装
int n;
char s[N];
int cnt[N],tmp[N],rk[N],sa[N],lcp[N];
void PreMake(){
memset(cnt,0,800);
rep(i,1,n) cnt[(int)s[i]]++;
rep(i,1,200) cnt[i]+=cnt[i-1];
rep(i,1,n) rk[i]=cnt[(int)s[i]],sa[i]=i; //瞎初始化一波,不用我这样写
rep(i,n+1,n*2) rk[i]=0;// 注意一下边界的清空
for(reg int k=1;k<=n;k<<=1) {
rep(i,0,n) cnt[i]=0;
rep(i,1,n) cnt[rk[i+k]]++;
rep(i,1,n) cnt[i]+=cnt[i-1];
drep(i,n,1) tmp[cnt[rk[i+k]]--]=i; // 按照第二关键字排序
rep(i,0,n) cnt[i]=0;
rep(i,1,n) cnt[rk[i]]++;
rep(i,1,n) cnt[i]+=cnt[i-1];
drep(i,n,1) sa[cnt[rk[tmp[i]]]--]=tmp[i];//按照第一关键字排序,求出 sa
rep(i,1,n) tmp[sa[i]]=tmp[sa[i-1]]+(rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i]+k]!=rk[sa[i-1]+k]);
rep(i,1,n) rk[i]=tmp[i];//求出rk,注意相同的
}
}
遅い泥棒を測定し、このボードはいけません。。。
\ [\ \]
\ [\ \]
1-2 LCP
SAのもう一つの重要な一部である\(LCP \)配列(と呼ばれるいくつかの場所で\(高さ\)の配列、それは問題ではありません)
\(LCP \) :一般的な最長プレフィックス、最長の共通のプレフィックス
\(LCP [I] \): \(LCP(Suf_ {SA [I]}、{Suf_ SA [I + 1]})\)
性质1:\(LCP(Suf_i、Suf_j)=分(LCP(Suf_i、Suf_k)、LCP(Suf_k、Suf_j))(RK [I] \当量RK [K] \当量RK [J])\)
まず、任意の文字列を\(S_1、S_2、S_3 \)がある(LCP(S_1、S_2)\ GE分(LCP(S_1、S_3)、LCP(S_2、S_3は))\)\、おそらくことは言うまでもないです
そして、証拠$ LCP(Suf_i、Suf_j)>分(LCP(Suf_i、Suf_k)、LCP(Suf_k、Suf_j))$欠席
设\(LCP(Suf_i、Suf_k)=、LCP(Suf_k、Suf_j)= B \)
もし\(> B \)がある\(のS_ {J + B} \ S_のNE {K + B} \) 、しかし理由\(> B \)であることができる\(S_ {K + B} = S_ I + B} {\) 、すなわち\(S_ {I + B} \ NE S_ {J + bが} \) のでないあります
もし\(B> A \) 、共感
もし\(A = B \)次に、\(S_ {I + A}の\ S_ S_ {J + A} \の{K + A} \ NEのS_ {K + A}、のNE) 、及びため辞書式順序の順序でので、そこ\(S_のI S_の{} + <K + S_ {} + \の{} <J) 、同じことが、上記の場合に排除することができます
(自分自身のうち、この量はかろうじてそれを参照してください)証明されました
\ [\ \]
性质2:\(LCP [RK [I + 1] \ GE LCP [RK [I]] - 1 \)
事实上\(LCP [RK [I] = LCP(Suf_i、Suf_ {SA [RK [I] -1]})\)
另\(Suf_i =、Suf_ {SA [RK [I] -1]} = B、Suf_ {iが+ 1} = C、Suf_ {SA [RK [I + 1] -1]} = D、LCP [ RK [I] = X、LCP [RK [I + 1] = Y \)
以下の説明のみ\(X \ GE 2 \)状況、(X- \のLeq 1 \)\ケース量。。。
\(C \)文字列である\(A \)最初の文字を除去するので、そこ\(A_ {1、X} = B_ {1、X}、A_ {2、X} = C_ {1、X-1} \)
今\(D \)が辞書未満である\(C \)場合、\(D_ {1、X- 1 } \ NE C_ {1、X-1} \)次に、D_ {1、X-(\ 1 } <C_ {1、X- 1} \)
そして我々はすでに知っているがサフィックス\(E = B_ {2、 lenの(B)} \) を満足\(E_ {1、X- 1} = C_ {1、X-1} \) ので\(X \ GE 2 \)がある)\ E <C(\
\(D <E <C \ ) 競合
したがって\(D_ {1、X- 1} = C_ {1、X-1} \)
プロパティ2に従って求めることができる(\)O(N)\処理(LCP \)\ array-
for(reg int i=1,h=0;i<=n;++i) {
if(h) h--; // LCP[rk[i+1]]>=LCP[rk[i]]
int j=sa[rk[i]-1];
while(i+h<=n && j+h<=n && s[i+h]==s[j+h]) h++;
lcp[rk[i]-1]=h;
}
//由于0<=h<=n,h最多减少n次,所以h最多增加n*2次
\ [\ \]
1-3アプリケーション:
1:クエリ\(LCP(S_ {I、 n}は、S_ {J、N})\)
自然の1によっては、それがために変換することができます\(分(LCP [RK [ i]が.. RK [J] -1])(RK [I] \当量RK [J])\)
STとテーブルを維持するために、国境問題について注意/セグメントツリー
\ [\ \]
2:さまざまな要件のサブ文字列の数
サブストリングソートするための(SA [I] \)\、答えは\(\和N-SAは、[ I] + 1-LCP [I-1] \)
以下のための\(SA [I] \)サフィックス設け\(N-SA [i]を +1 \) 接頭辞、接頭辞辞書式に出現した文字列の数が最大値未満である\(LCP(Suf_i、 Suf_j)\) 、すなわち\(LCP [I-1] \)
\ [\ \]
3.要求LCS
2つのシリーズ一緒に、いくつかの奇妙な文字で真ん中
そして、インデックスは2つの文字列が全てです落ちる求めている\(I、J \)で\(LCP(Suf_i、Suf_j) \) 最大
よると、(SA \)\シーケンスしか最近考える見つけることができます\(I、J \)ので、各\(I \)最寄り見つける\(jは\)することができ、定規を取ることです
\ [\ \]
。4:\(K \)大サブストリング
接尾辞配列が既にソートされ、ために可能であるので\(SA [I] \)の数への寄与を検討するために(N-SAを[I] \ [I-1] \ + 1-LCP)
そして、蓄積されたプレフィックスの数を考えると\(SUM [I] \) 、上の2点\(合計は、[P] \ GE kは\) するサフィックス文字列を探して知ることができる(P \)\プレフィックスエピソードが、この接尾辞は、複数回発生する可能性があります
所定の長さ\(LEN = K和[ P-1] + LCPは[P-1] \) のランキングが発生していると結合されています
全ての接尾辞文字列が連続したセグメントである含む\(L、R \)を満足\(\ forall_ {I \で [L、R]} LCP(SA [i]は、P)\ GE LEN \)
あなたは、いくつか解決することができる問題を
\ [\ \]
5:文字列の長さは、ほとんどの時間を表示された最長の文字列が発生し、少なくともx回、少なくともxであります
我々が可能な第1ケース(\ LCP)を\配列セグメントは、各セグメント\([I] \ GE X \ LCP)は、これらのサフィックスの長さが表示され\(Xを\)プレフィックスは、次に、統計同じです各セグメントは、いくつかの接尾まで含めることができます
後者の場合は、直接の半分を設定することができます。。。
重複要求がある場合はケースの一部は、の位置から見えるかを決定しますすることはできません1743 - POJ
:このグループのようにも次のような多くの問題、解決することができPOJ-3294を
\ [\ \]
6. LCP要求サイクルの使用
\(LCP(Suf_i、Suf_j) \ GEのJ-I + 1(I \当量J)\) が登場サイクルの長さに一致するサイクルの数に応じて決定することができます
もちろん、他のいくつかの方法がありますが、原則は似ています
問題ポータルコレクションに例ソリューション: