【工艺】

好像是最小表示法的板子题呢

但是不会啊,于是就变成了我的第一道(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;
}
原文地址:https://www.cnblogs.com/asuldb/p/10207916.html