• 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
    ", calculateAutomaton());
    102 }

    @Author: YouSiki

  • 相关阅读:
    ffmpeg
    HDU 1031 Design T-Shirt
    HDU 1029 Ignatius and the Princess IV
    HDU 1022 Train Problem I
    HDU 1017 A Mathematical Curiosity
    HDU 1015 Safecracker
    HDU 1002 A + B Problem II
    HDU 1070 Milk
    高精度算法(一)
    codeblocks 使用心得
  • 原文地址:https://www.cnblogs.com/yousiki/p/6212878.html
Copyright © 2020-2023  润新知