【工艺】
好像是最小表示法的板子题呢
但是不会啊,于是就变成了我的第一道\(SAM\)
对于这种跟循环同构有关系的题,显然需要将原来的串倍长,之后先插入到\(SAM\)里去
之后我们在\(SAM\)上找到贪心访问最小的儿子找到一条长度为\(n\)的路径就好了
显然因为我们循环同构了,所以从根到根的任何一个转移必然会存在一个长度为\(n\)的路径
字符集很大,需要开\(map\)
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#define re register
#define LL long long
#define maxn 600005
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
re char c=getchar();int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
std::map<int,int> son[maxn<<1];
int a[maxn];
int link[maxn<<1],len[maxn<<1],sz[maxn<<1];
int lst=1,n,m,cnt=1,now=0;
inline void ins(int c)
{
int f=lst,p=++cnt; lst=p;
len[p]=len[f]+1,sz[p]=1;
while(f&&!son[f][c]) son[f][c]=p,f=link[f];
if(!f) {link[p]=1;return;}
int x=son[f][c];
if(len[f]+1==len[x]) {link[p]=x;return;}
int y=++cnt;
len[y]=len[f]+1,link[y]=link[x],link[x]=link[p]=y;
for(std::map<int,int>::iterator i=son[x].begin();i!=son[x].end();++i) son[y].insert(*i);
while(f&&son[f][c]==x) son[f][c]=y,f=link[f];
}
void dfs(int x)
{
if(now==n) return;
std::map<int,int>::iterator i=son[x].begin();
int t=(*i).first;
printf("%d ",t);now++;
dfs((*i).second);
}
int main()
{
n=read();
for(re int i=1;i<=n;i++) a[i]=a[i+n]=read();
for(re int i=1;i<=2*n;i++) ins(a[i]);
dfs(1);
return 0;
}