[POI 2000] 公共串

[题目链接]

        https://www.lydsy.com/JudgeOnline/problem.php?id=2946

[算法]

         建立多串后缀树

         对于后缀树上的每个点 , 判断该节点所代表的等价类是否在所以字符串中出现 , 用该点的深度更新答案

         时间复杂度 : O(NL)

[代码] 

       

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e5 + 10;
const int ALPHA = 26;

int n , ans;
char s[N];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}

struct Suffix_Automaton
{
        int sz , last;
        int father[N] , child[N][ALPHA] , depth[N];
        bool lab[N][6];
        vector< int > a[N];
        Suffix_Automaton()
        {
                sz = 1;
                last = 1;        
        }        
        inline int new_node(int dep)
        {
                depth[++sz] = dep;
                father[sz] = 0;
                memset(child[sz] , 0 , sizeof(child[sz]));
                memset(lab[sz] , 0 , sizeof(lab[sz]));
                return sz;
        }
        inline void extend(int ch , int c)
      {
        int np = child[last][ch];
        if (np)
        {
            if (depth[np] == depth[last] + 1) 
            {
                lab[np][c] = true;
                last = np;
            } else
            {
                int nq = new_node(depth[last] + 1);
                father[nq] = father[np];
                father[np] = nq;
                memcpy(child[nq] , child[np] , sizeof(child[nq]));
                for (int p = last; child[p][ch] == np; p = father[p]) 
                        child[p][ch] = nq;
                lab[nq][c] = true;
                last = nq;
            }
        } else
        {
              int np = new_node(depth[last] + 1);
              int p = last;
              while (child[p][ch] == 0)
              {
                  child[p][ch] = np;
                  p = father[p];
              }
              if (child[p][ch] == np)
              {
                  father[np] = 1;
                  lab[np][c] = true;
                  last = np;
                  return;
              }
              int q = child[p][ch];
              if (depth[q] == depth[p] + 1)
              {
                  father[np] = q;
                  lab[np][c] = true;
                  last = np;
                  return; 
              } else
              {
                  int nq = new_node(depth[p] + 1);
                  father[nq] = father[q];
                  father[np] = father[q] = nq;
                  memcpy(child[nq] , child[q] , sizeof(child[q]));
                  while (child[p][ch] == q)
                  {
                      child[p][ch] = nq;
                      p = father[p];
                  }
                  lab[np][c] = true;
                  last = np;
                  return;
              }
        }
         }
        inline void insert(char *s , int col)
        {
                last = 1;
                for (int i = 1; i <= strlen(s + 1); ++i)
                        extend(s[i] - 'a' , col);
        }
        inline void dfs(int u)
        {
                for (unsigned i = 0; i < a[u].size(); ++i)
                {
                        int v = a[u][i];
                        dfs(v);
                        for (int j = 1; j <= n; ++j)
                                lab[u][j] |= lab[v][j];
                }
                bool all = true;
                for (int i = 1; i <= n; ++i) all &= lab[u][i];
                if (all) chkmax(ans , depth[u]);
        }
        inline void work()
        {
                for (int i = 2; i <= sz; ++i)
                        a[father[i]].push_back(i);
                dfs(1);
        }
} SAM;

int main()
{
        
        read(n);
        for (int i = 1; i <= n; ++i)
        {
                scanf("%s" , s + 1);
                SAM.insert(s , i);
        }
        SAM.work();
        printf("%d\n" , ans);
        
        return 0;
    
}

 

posted @ 2019-04-05 21:12  evenbao  阅读(164)  评论(0编辑  收藏  举报