[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

 

posted @ 2017-06-11 11:15  zht467  阅读(208)  评论(0编辑  收藏  举报