Luogu4051 / BZOJ1031暗号化された文字の[JSOI2007]接尾辞配列

トピックポータル

アルゴリズム分析

この問題は、リングの文字列のサフィックスのソートに相当し、この問題に関する一般的なポリシーの処理ループがされ破环为链、その後、元の文字列は、この新しい文字列のサフィックスのソートをバックにコピー元の文字列を倍増しました。

なぜ、このアルゴリズムは正しいですか?サフィックス\(> 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;
}

おすすめ

転載: www.cnblogs.com/ZigZagKmp/p/11479796.html
おすすめ