UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)

题目大意:

给出一个长度为N的字符串,求其字典序最小的循环同构。

N<=10W。

算法讨论:

算法一、最小表示法。定义题。

算法二、后缀自动机。

 

Codes:

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <cassert>
  7 using namespace std;
  8 const int L = 10000 + 5;
  9 
 10 int ans = 0;
 11 char str[L<<2];
 12 
 13 struct State{
 14   int len, pre;
 15   int next[26];
 16 
 17   State(){
 18     len = pre = 0;
 19     memset(next, 0, sizeof next);
 20   }
 21   void clear(){
 22     len = pre = 0;
 23     memset(next, 0, sizeof next);
 24   }
 25 }st[L<<2];
 26 
 27 struct SuffixAutomaton{
 28   int sz, last;
 29 
 30   void Init(){
 31     last = 0;
 32     sz = 0;
 33     for(int i = 0; i < (L<<2); ++ i)
 34       st[i].clear();
 35     st[0].len = 0; st[0].pre = -1;
 36     sz ++;
 37   }
 38   void Extend(int c){
 39     int cur = sz ++;
 40     st[cur].len = st[last].len + 1;
 41     int p;
 42 
 43     for(p = last; p != -1 && !st[p].next[c]; p = st[p].pre)
 44       st[p].next[c] = cur;
 45 
 46     if(p == -1) st[cur].pre = 0;
 47     else{
 48       int q = st[p].next[c];
 49       if(st[q].len == st[p].len + 1) st[cur].pre = q;
 50       else{
 51         int cle = sz ++;
 52         st[cle].len = st[p].len + 1;
 53         st[cle].pre = st[q].pre;
 54         for(int i = 0; i < 26; ++ i) st[cle].next[i] = st[q].next[i];
 55         for(; p != -1 && st[p].next[c] == q; p = st[p].pre)
 56           st[p].next[c] = cle;
 57         st[q].pre = st[cur].pre = cle;
 58       }
 59     }
 60     last = cur;
 61   }
 62 }SAM;
 63 
 64 void Input(){
 65   scanf("%s", str);
 66 }
 67 
 68 void Output(){
 69   printf("%d\n", ans);
 70 }
 71 
 72 void Solve(){
 73   int len = strlen(str);
 74   SAM.Init();
 75   for(int i = 0; i < len; ++ i)
 76     str[i + len] = str[i];
 77   for(int i = 0; i < (len<<1); ++ i){
 78     SAM.Extend(str[i] - 'a');
 79   }
 80 
 81   int p = 0;
 82   for(int i = 0; i < len; ++ i){
 83     for(int j = 0; j < 26; ++ j){
 84       if(st[p].next[j]){
 85         p = st[p].next[j];
 86         break;
 87       }
 88     }
 89   }
 90 
 91   ans = st[p].len - len + 1;
 92 }
 93 
 94 int main(){
 95   int t;
 96   scanf("%d", &t);
 97   while(t --){
 98     Input();
 99     Solve();
100     Output();
101   }
102   return 0;
103 }
后缀自动机

 

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