天天看点

SPOJ LCS2 Longest Common Substring II

Description

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn't exist, print "0" instead.

Example

Input:

alsdfkjfjkdsal

fdjskalajfkdsla

aaaajfaaaa

Output:

2

Notice: new testcases added

后缀自动机

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 300005;
char s[maxn];

class SAM
{
  const static int maxn = 500005;   //节点个数  
  const static int size = 26;     //字符的范围  
  const static char base = 'a';     //字符的基准  

  class node
  {
  public:
    node *fa, *next[size];
    int len, cnt[10];
    node* clear(int x)
    {
      fa = 0; len = x;
      memset(cnt, 0, sizeof(cnt));
      memset(next, 0, sizeof(next));
      return this;
    }
  }nd[maxn];                      //节点的设置  

  node *root, *last;              //根节点,上一个节点  
  int tot;                        //总节点数  
public:
  void clear()
  {
    last = root = &nd[tot = 0];
    nd[0].clear(0);
  }                               //初始化  
  void insert(char ch)
  {
    node *p = last, *np = nd[++tot].clear(p->len + 1);
    last = np;
    int x = ch - base;
    while (p&&p->next[x] == 0) p->next[x] = np, p = p->fa;
    if (p == 0) { np->fa = root; return; }

    node* q = p->next[x];
    if (p->len + 1 == q->len) { np->fa = q; return; }

    node *nq = nd[++tot].clear(p->len + 1);
    for (int i = 0; i < size; i++)
      if (q->next[i]) nq->next[i] = q->next[i];
    nq->fa = q->fa;
    q->fa = np->fa = nq;
    while (p &&p->next[x] == q) p->next[x] = nq, p = p->fa;
  }                               //插入操作  

  void find(char *ch, int y)
  {
    node *s = root;
    int maxlen = 0;
    for (int i = 0; ch[i]; i++)
    {
      int x = ch[i] - base;
      if (s->next[x]) 
      {
        s = s->next[x];
        s->cnt[y] = max(s->cnt[y], ++maxlen);
      }
      else
      {
        while (s&&!s->next[x])
        {
          s->cnt[y] = max(s->cnt[y], maxlen);
          s = s->fa;
        }
        if (s == 0) s = root,maxlen = 0;
        else
        {
          maxlen = s->len + 1; s = s->next[x];
          s->cnt[y] = max(s->cnt[y], maxlen);
        }
      }
    }
  }
  void query(int x)
  {
    int ans = 0;
    for (int i = tot; i; i--)
    {
      int u = nd[i].len;
      for (int j = 0; j < x; j++) u = min(u, nd[i].cnt[j]);
      ans = max(ans, u);
    }
    printf("%d\n", ans);
  }
}sam;

int main()
{
  scanf("%s", s);
  sam.clear();
  for (int i = 0; s[i]; i++) sam.insert(s[i]);
  int j;
  for (j = 0; ~scanf("%s", s); j++) sam.find(s, j);
  sam.query(j);
  return 0;
}