【Luogu】P 3809接尾辞並べ替え(接尾辞配列テンプレート)
7602 ワード
タイトルリンク
今日やっと接尾辞配列テンプレートqwqを習得しました
テンプレートemmmmしかできません
まず青い本emmmmを持っています
それから青い本の221ページのコードを見てから私は理解できませんでした.
そこでrqyを出してください
rqy:
最初は単一の文字をソートする操作だったでしょう
c[i]は、iの値を持つ文字の数を表す
x[i]i番目の位置の優先度を示す
sa[i]は、優先度がiの文字位置を示す
最初の行は明らかに初期化され、2番目の行は明らかに統計文字の数です.
3行目にはなぜ接頭辞和が要求されるのでしょうか.
優先順位が小さいほど上位になると考えています
したがって,優先度が0のものをc[0]個,優先度が1のものをc[1]個とする.
だから、私たちはc[0]文字を「0」と仮定して、[0,c[0])区間に並んで左閉右開にしなければならない.
次に、c[1]文字を切り取って「1」と仮定し、[c[0],c[0]+c[1])区間を左閉右開に並べなければならない
そしてこのように推す
cの接頭辞とSを簡単に覚えてみましょう
そこで我々が並べ替えた区間は[0,S[0])[S[0],S[1])[S[1],S[2])になった.
ちょっと待って.
そして楽しい基数ソートができます
2つのキーワードのソート方法を考えてみましょう
つまり、私はまず第2のキーワードを並べて、それからソートアルゴリズムが安定していることを保証して、第1のキーワードを並べます.
2番目のキーワードは直接列挙することができます.第1キーワード......基数ソートはqwqを解決することができる.
次に隣接する2つの接尾辞番号が等しいかどうかを見て、等しい説明で区別できなかったら、並んで、等しくなければ退出できます.
転載先:https://www.cnblogs.com/cellular-automaton/p/8277739.html
今日やっと接尾辞配列テンプレートqwqを習得しました
テンプレートemmmmしかできません
まず青い本emmmmを持っています
それから青い本の221ページのコードを見てから私は理解できませんでした.
そこでrqyを出してください
rqy:
最初は単一の文字をソートする操作だったでしょう
c[i]は、iの値を持つ文字の数を表す
x[i]i番目の位置の優先度を示す
sa[i]は、優先度がiの文字位置を示す
最初の行は明らかに初期化され、2番目の行は明らかに統計文字の数です.
3行目にはなぜ接頭辞和が要求されるのでしょうか.
優先順位が小さいほど上位になると考えています
したがって,優先度が0のものをc[0]個,優先度が1のものをc[1]個とする.
だから、私たちはc[0]文字を「0」と仮定して、[0,c[0])区間に並んで左閉右開にしなければならない.
次に、c[1]文字を切り取って「1」と仮定し、[c[0],c[0]+c[1])区間を左閉右開に並べなければならない
そしてこのように推す
cの接頭辞とSを簡単に覚えてみましょう
そこで我々が並べ替えた区間は[0,S[0])[S[0],S[1])[S[1],S[2])になった.
ちょっと待って.
そして楽しい基数ソートができます
2つのキーワードのソート方法を考えてみましょう
つまり、私はまず第2のキーワードを並べて、それからソートアルゴリズムが安定していることを保証して、第1のキーワードを並べます.
2番目のキーワードは直接列挙することができます.第1キーワード......基数ソートはqwqを解決することができる.
次に隣接する2つの接尾辞番号が等しいかどうかを見て、等しい説明で区別できなかったら、並んで、等しくなければ退出できます.
#include
#include
#include
#include
#include
#define maxn 2000100
using namespace std;
inline long long read(){
long long num=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
num=num*10+ch-'0';
ch=getchar();
}
return num*f;
}
char s[maxn];
int sa[maxn];
int x[maxn];
int y[maxn];
int c[maxn];
int len;
void build(int m){
for(int i=0;i<=m;++i) c[i]=0;
for(int i=1;i<=len;++i) c[x[i]=s[i]]++;
for(int i=1;i<=m;++i) c[i]+=c[i-1];
for(int i=len;i>=1;--i) sa[c[x[i]]--]=i;
for(int k=1;k<=len;k<<=1){
int p=0;
for(int i=len-k+1;i<=len;++i) y[++p]=i;
for(int i=1;i<=len;++i)
if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=0;i<=m;++i) c[i]=0;
for(int i=1;i<=len;++i) c[x[y[i]]]++;
for(int i=1;i<=m;++i) c[i]+=c[i-1];
for(int i=len;i>=1;--i) sa[c[x[y[i]]]--]=y[i];
std::swap(x,y);
p=1; x[sa[1]]=1;
for(int i=2;i<=len;++i)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
if(p>=len) break;
m=p;
}
}
int main(){
scanf("%s",s+1);
len=strlen(s+1);
build(200);
for(int i=1;i<=len;++i) printf("%d ",sa[i]);
return 0;
}
転載先:https://www.cnblogs.com/cellular-automaton/p/8277739.html