BZOJ 2946: [Poi2000]公共串

2946: [Poi2000]公共串

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 787  Solved: 342
[Submit][Status][Discuss]

Description

 
       给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l        读入单词
l        计算最长公共子串的长度
l        输出结果
 

Input

 
文件的第一行是整数 n1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000
 

Output

仅一行,一个整数,最长公共子串的长度。
 

Sample Input

3
abcb
bca
acbc

Sample Output

HINT

Source

[Submit][Status][Discuss]

 

求若干字符串的最长公共子串。

和SPOJ的那道题简直一模一样,后缀自动机。

 

  1 #include <bits/stdc++.h>
  2 
  3 const int maxn = 5e5 + 5;
  4 
  5 /* AUTOMATON */
  6 
  7 int last;
  8 int tail;
  9 int mini[maxn];
 10 int maxi[maxn];
 11 int step[maxn];
 12 int fail[maxn];
 13 int next[maxn][26];
 14 
 15 inline void buildAutomaton(char *s)
 16 {
 17     last = 1;
 18     tail = 2;
 19     while (*s)
 20     {
 21         int c = *s++ - 'a';
 22         int p = last;
 23         int t = tail++;
 24         step[t] = step[p] + 1;
 25         mini[t] = maxi[t] = step[t];
 26         while (p && !next[p][c])
 27             next[p][c] = t, p = fail[p];
 28         if (p)
 29         {
 30             int q = next[p][c];
 31             if (step[q] == step[p] + 1)
 32                 fail[t] = q;
 33             else
 34             {
 35                 int k = tail++;
 36                 fail[k] = fail[q];
 37                 fail[q] = fail[t] = k;
 38                 step[k] = step[p] + 1;
 39                 mini[k] = maxi[k] = step[k];
 40                 for (int i = 0; i < 26; ++i)
 41                     next[k][i] = next[q][i];
 42                 while (p && next[p][c] == q)
 43                     next[p][c] = k, p = fail[p];
 44             }
 45         }
 46         else
 47             fail[t] = 1;
 48         last = t;
 49     }
 50 }
 51 
 52 inline void searchAutomaton(char *s)
 53 {
 54     memset(maxi, 0, sizeof(maxi));
 55     for (int t = 1, k = 0; *s; )
 56     {
 57         int c = *s++ - 'a';
 58         if (next[t][c])
 59             ++k, t = next[t][c];
 60         else
 61         {
 62             while (t && !next[t][c])
 63                 t = fail[t];
 64             if (t)
 65                 k = step[t] + 1, t = next[t][c];
 66             else   
 67                 k = 0, t = 1;
 68         }
 69         if (maxi[t] < k)
 70             maxi[t] = k;
 71     }
 72     for (int i = tail - 1; i; --i)
 73         if (maxi[fail[i]] < maxi[i])
 74             maxi[fail[i]] = maxi[i];
 75     for (int i = 1; i < tail; ++i)
 76         if (mini[i] > maxi[i])
 77             mini[i] = maxi[i];
 78 }
 79 
 80 inline int calculateAutomaton(void)
 81 {
 82     register int ret = 0;
 83     for (int i = 1; i < tail; ++i)
 84         if (ret < mini[i])
 85             ret = mini[i];
 86     return ret;
 87 }
 88 
 89 /* MAIN FUNC */
 90 
 91 char str[maxn];
 92 
 93 signed main(void)
 94 {
 95     int n; 
 96     scanf("%d", &n);
 97     scanf("%s", str);
 98     buildAutomaton(str);
 99     for (int i = 1; i < n; ++i)
100         scanf("%s", str), searchAutomaton(str);
101     printf("%d\n", calculateAutomaton());
102 }

 

@Author: YouSiki

posted @ 2016-12-22 21:15  YouSiki  阅读(237)  评论(0编辑  收藏  举报