BZOJ 2882 工艺 (字符串最小循环同构)

题目大意:

给一个长度小于等于30W的数列,求其最小循环同构。

算法讨论:

在自动机长倍长走S后即可。注意这里面是数字,要用map存储。 今天才知道要开四倍长。

Codes:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int L = 300000 + 5;
  5 
  6 int n, a[L<<1], ans;
  7 
  8 struct State{
  9   int len, pre;
 10   map <int, int> next;
 11   
 12   State(){
 13     len = pre = 0;
 14     next.clear();
 15   }
 16   void clear(){
 17     len = pre = 0;
 18     next.clear();
 19   }
 20 }st[L<<1];
 21 
 22 struct SuffixAutomaton{
 23   int sz, last;
 24 
 25   void Init(){
 26     last = sz = 0;
 27     st[0].len = 0; st[0].pre = -1;
 28     sz ++;
 29   }
 30   void Extend(int c){
 31     int cur = sz ++;
 32     st[cur].len = st[last].len + 1;
 33     int p;
 34 
 35     for(p = last; p != -1 && !st[p].next[c]; p = st[p].pre)
 36       st[p].next[c] = cur;
 37 
 38     if(p == -1) st[cur].pre = 0;
 39     else{
 40       int q = st[p].next[c];
 41       if(st[q].len == st[p].len + 1) st[cur].pre = q;
 42       else{
 43         int cle = sz ++;
 44         st[cle].len = st[p].len + 1;
 45         st[cle].pre = st[q].pre;
 46         st[cle].next = st[q].next;
 47         for(; p != -1 && st[p].next[c] == q; p = st[p].pre)
 48           st[p].next[c] = cle;
 49         st[q].pre = st[cur].pre = cle;
 50       }
 51     }
 52     last = cur;
 53   }
 54 }SAM;
 55 
 56 void Input(){
 57   scanf("%d", &n);
 58   for(int i = 0; i < n; ++ i)
 59     scanf("%d", &a[i]);
 60 }
 61 void Output(){
 62   bool flag = false;
 63   for(int i = ans; i < ans + n; ++ i){
 64     if(!flag){
 65       flag = true;
 66       printf("%d", a[i % n]);
 67     }
 68     else
 69       printf(" %d", a[i % n]);
 70   }
 71     
 72   printf("\n");
 73 }
 74 
 75 void Solve(){
 76   SAM.Init();
 77   for(int i = 0; i < n; ++ i)
 78     a[i + n] = a[i];
 79   for(int i = 0; i < (n<<1); ++ i)
 80     SAM.Extend(a[i]);
 81 
 82   int p = 0;
 83   map <int, int>:: iterator pos;
 84   
 85   for(int i = 0; i < n; ++ i){
 86     for(pos = st[p].next.begin(); pos != st[p].next.end(); ++ pos){
 87       p = (*pos).second;
 88       break;
 89     }
 90   }
 91 
 92   ans = st[p].len - n;
 93 }
 94 
 95 int main(){
 96 
 97   Input();
 98   Solve();
 99   Output();
100 
101   return 0;
102 }
BZOJ 2882

 

posted @ 2016-01-16 21:15  漫步者。!~  阅读(314)  评论(0编辑  收藏  举报