bzoj 2882 工艺
思路:
这是字符串最大最小表示法的题,今天用后缀自动机做一下。
sam:
#include <bits/stdc++.h> using namespace std; struct SAM { static const int MAXN = 300001<<1;//大小为字符串长度两倍 map<int,int>ch[MAXN]; int tot, last, fa[MAXN], len[MAXN]; int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组 void init( void) { last = tot = 1; } void add( int x) { int p = last, np = last = ++tot; len[np] = len[p] + 1, cnt[last] = 1; while( p && !ch[p].count(x)) ch[p][x] = np, p = fa[p]; if( p == 0) fa[np] = 1; else { int q = ch[p][x]; if( len[q] == len[p] + 1) fa[np] = q; else { int nq = ++tot; ch[nq]=ch[q]; len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq; while( p && ch[p].count(x) && ch[p][x] == q) ch[p][x] = nq, p = fa[p]; } } } void toposort( void) { for(int i = 1; i <= len[last]; i++) sum[i] = 0; for(int i = 1; i <= tot; i++) sum[len[i]]++; for(int i = 1; i <= len[last]; i++) sum[i] += sum[i-1]; for(int i = 1; i <= tot; i++) tp[sum[len[i]]--] = i; for(int i = tot; i; i--) cnt[fa[tp[i]]] += cnt[tp[i]]; } void solve( int n) { for(int i=1,p=1;i<=n;i++) printf("%d ",ch[p].begin()->first),p=ch[p].begin()->second; } } sam; int a[300003]; int main(void) { int n;cin>>n; sam.init(); for(int i=1;i<=n;i++) scanf("%d",a+i),sam.add(a[i]); for(int i=1;i<=n;i++) sam.add(a[i]); sam.solve(n); return 0; }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。