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 }