アルゴリズム分析
この問題は、リングの文字列のサフィックスのソートに相当し、この問題に関する一般的なポリシーの処理ループがされ破环为链
、その後、元の文字列は、この新しい文字列のサフィックスのソートをバックにコピー元の文字列を倍増しました。
なぜ、このアルゴリズムは正しいですか?サフィックス\(> N \)文字列の一部が答えには影響しないのだろうか?
我々だけで最初の新しい文字列接尾辞に焦点を当てているため、\(N \)の位置、そして唯一の2つのサフィックスが会う前に\(N \)ビットが同一であるが、後の時間を比較されますが、この状況では唯一のような形になるaaaaa
。この文字列が表示され、何で文字列のソート順序が結果に影響を与えないことは明らかです。
2回のオープンスペースに注意してください!!!
コードの実装
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005//错误笔记:复制二倍数组没开够
#define maxm 400005
char s[maxn];
int n;
int sa[2][maxn],rk[2][maxn],v[maxn];
int main(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++)s[i+n]=s[i];
n=strlen(s+1);
int p=0,q=1;
for(int i=1;i<=n;i++)v[s[i]]++;
for(int i=1;i<128;i++)v[i]+=v[i-1];
for(int i=1;i<=n;i++)sa[0][v[s[i]]--]=i;
for(int i=1;i<=n;i++)rk[0][sa[0][i]]=rk[0][sa[0][i-1]]+(s[sa[0][i-1]]!=s[sa[0][i]]);
for(int k=1;k<=n;(k<<=1),swap(p,q)){
for(int i=1;i<=n;i++)v[rk[p][sa[p][i]]]=i;
for(int i=n;i;i--)
if(sa[p][i]>k)sa[q][v[rk[p][sa[p][i]-k]]--]=sa[p][i]-k;
for(int i=n-k+1;i<=n;i++)sa[q][v[rk[p][i]]--]=i;
for(int i=1;i<=n;i++)rk[q][sa[q][i]]=rk[q][sa[q][i-1]]+((rk[p][sa[q][i]]!=rk[p][sa[q][i-1]])||(rk[p][sa[q][i]+k]!=rk[p][sa[q][i-1]+k]));
if(rk[q][sa[q][n]]==n)break;
}
for(int i=1;i<=n;i++)
if(sa[q][i]<=n/2)printf("%c",s[sa[q][i]+n/2-1]);
return 0;
}