明日続けるために、スリープ状態にブロガー
接尾辞配列の定義:
接尾辞配列(接尾辞配列は)のストリングを指すすべてのサフィックスに従ってソートする辞書取り戻すための配列。配列のみ店舗位置サフィックスを開始します。
サフィックス:元の文字列と空の文字列を含む端まで開始位置から文字列の文字列ストリング。
例:{ABC}接尾辞{ABC}、{BC}、 {C}、{}
小規模から大規模までデフォルト:によって辞書のソート
接尾辞配列の構築:
シンプルなアプローチ:n番目のソートソート文字列、時間の複雑\(O(N ^ 2log_2n) \)
乗算器アレイ方法:Manberとマイヤーズ発明の必要\(log_2nの\)倍、ソート時間複雑度\(O(nlog_2n)\) 、総時間の複雑さであるように\(O(nlog_2 ^ 2N)を\) 、缶ソート基数ソートをソートするために最適化され、総時間の複雑さをするように最適化された\(O(nlog_2n)\) 。
だから、一般的には、十分な配列を倍増させる方法は、より速く行くことができます[ IS-ためのSAアルゴリズム ]
コード配列を掛けます:
最適化されていないコード
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1000
using namespace std;
char str[MAXN];//字符串数组
int sa[MAXN + 1];//后缀数组,+1是为了存储(空字符串)
int rank[MAXN + 1];//Rank[i]第i位开始的子串排名(0~N)
int tmp[MAXN+1];
int k,n;
bool cmp_sa(const int &i,const int &j) {
if(rank[i] != rank[j]) return rank[i]<rank[j];
else {
int l = n-i>=k?rank[i+k]:-1;
int r = n-j>=k?rank[j+k]:-1;
return l<r;
}
return true;
}
void build_sa(const char* str,int *sa) {
n = strlen(str);
//长度为1的sa,rank取编码,因为空字符串排最前,所以取-1
for(int i=0; i<=n; i++) {
sa[i] = i;
rank[i] = rank[i] < n? str[i]:-1;
}
//用长度为i的Rank求长度为k的Rank
for(k=1; k<=n; k*=2) {
sort(sa,sa+n+1,cmp_sa);
tmp[sa[0]] = 0;
for(int i=1; i<=n; i++) {//计算Rank
tmp[sa[i]] = tmp[sa[i-1]] + (cmp_sa(sa[i-1],sa[i])?1:0);
}
for(int i=0; i<=n; i++) {
rank[i] = tmp[i];
}
}
}
int main() {
scanf("%s",&str);
build_sa(str,sa);
return 0;
}
トピック:
継続するには
参考ブログと文学:
https://www.cnblogs.com/jinkun113/p/4743694.html
https://www.cnblogs.com/victorique/p/8480093.html
チャレンジプログラミングコンテスト(第2版)