首页 > 代码库 > [HDU2328]Corporate Identity(后缀数组)

[HDU2328]Corporate Identity(后缀数组)

传送门

 

求 n 个串的字典序最小的最长公共子串。

和 2 个串的处理方法差不多。

把 n 个串拼接在一起,中间连上一个没有出现过的字符防止匹配过界。

求出 height 数组后二分公共子串长度给后缀数组分组。

然后 check,每一组中是否所有的字符串都包含。

直接遍历 sa 数组,第一个满足的结果就是字典序最小的。

 

——代码

技术分享
  1 #include <cstdio>  2 #include <cstring>  3 #include <iostream>  4 #define N 900005  5 #define M 4001  6   7 int n, len, m, start;  8 int buc[N], x[N], y[N], sa[N], rank[N], height[N], belong[N];  9 char s[N], a[M]; 10 bool f[M]; 11  12 inline void build_sa() 13 { 14     int i, k, p; 15     for(i = 0; i < m; i++) buc[i] = 0; 16     for(i = 0; i < len; i++) buc[x[i] = s[i]]++; 17     for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 18     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i; 19     for(k = 1; k <= len; k <<= 1) 20     { 21         p = 0; 22         for(i = len - 1; i >= len - k; i--) y[p++] = i; 23         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 24         for(i = 0; i < m; i++) buc[i] = 0; 25         for(i = 0; i < len; i++) buc[x[y[i]]]++; 26         for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 27         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i]; 28         std::swap(x, y); 29         p = 1, x[sa[0]] = 0; 30         for(i = 1; i < len; i++) 31             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; 32         if(p >= len) break; 33         m = p; 34     } 35 } 36  37 inline void build_height() 38 { 39     int i, j, k = 0; 40     for(i = 0; i < len; i++) rank[sa[i]] = i; 41     for(i = 0; i < len; i++) 42     { 43         if(!rank[i]) continue; 44         if(k) k--; 45         j = sa[rank[i] - 1]; 46         while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++; 47         height[rank[i]] = k; 48     } 49 } 50  51 inline bool check(int k) 52 { 53     int i, cnt = 1; 54     memset(f, 0, sizeof(f)); 55     f[belong[sa[0]]] = 1; 56     for(i = 1; i < len; i++) 57         if(height[i] >= k) 58         { 59             if(!f[belong[sa[i]]]) cnt++; 60             f[belong[sa[i]]] = 1; 61             if(cnt == n) 62             { 63                 start = sa[i]; 64                 return 1; 65             } 66         } 67         else 68         { 69             memset(f, 0, sizeof(f)); 70             f[belong[sa[i]]] = 1; 71             cnt = 1; 72         } 73     return 0; 74 } 75  76 int main() 77 { 78     int i, j, l, r, mid, leng; 79     while(scanf("%d", &n) && n) 80     { 81         len = 0; 82         m = 256; 83         memset(belong, 0, sizeof(belong)); 84         for(i = 1; i <= n; i++) 85         { 86             scanf("%s", a); 87             for(j = 0; a[j] ^ \0; j++) s[len++] = a[j]; 88             s[len++] = #; 89             belong[len] = 1; 90         } 91         len--; 92         build_sa(); 93         build_height(); 94         for(i = 1; i < len; i++) belong[i] += belong[i - 1]; 95         l = 1, r = len, leng = 0, start = -1; 96         while(l <= r) 97         { 98             mid = (l + r) >> 1; 99             if(check(mid)) leng = mid, l = mid + 1;100             else r = mid - 1;101         }102         if(leng && start ^ -1)103         {104             for(i = start; i < start + leng; i++) putchar(s[i]);105             putchar(\n);106         }107         else puts("IDENTITY LOST");108     }109     return 0;110 } 
View Code

 

[HDU2328]Corporate Identity(后缀数组)