给出一个串,要求其循环同构串中字典序最小的那个
串翻倍建\(SAM\)然后从起点开始贪心的跑\(n\)次即可
当然也能用最小表示法来做
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 6e5+7;
int n,A[MAXN];
struct SAM{
int len[MAXN<<1],link[MAXN<<1],tot,last;
map<int,int> ch[MAXN<<1];
SAM(){ link[len[0] = tot = last = 0] = -1; }
void extend(int x){
int np = ++tot, p = last; len[np] = len[last] + 1;
while(p!=-1 and !ch[p].count(x)){
ch[p].insert(make_pair(x,np));
p = link[p];
}
if(p==-1) link[np] = 0;
else{
int q = ch[p].at(x);
if(len[p]+1==len[q]) link[np] = q;
else{
int clone = ++tot;
link[clone] = link[q];
ch[clone] = ch[q];
len[clone] = len[p] + 1;
while(p!=-1 and ch[p].count(x) and ch[p].at(x)==q){
ch[p].at(x) = clone;
p = link[p];
}
link[q] = link[np] = clone;
}
}
last = np;
}
void minimal_circle(){
int u = 0;
for(int i = 1; i <= n; i++){
printf("%d ",ch[u].begin()->first);
u = ch[u].begin()->second;
}
}
}sam;
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
for(int i = 1; i <= n; i++) sam.extend(A[i]);
for(int i = 1; i <= n; i++) sam.extend(A[i]);
sam.minimal_circle();
return 0;
}