后缀自动机(SAM):SPOJ Longest Common Substring II

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀自动机(SAM):SPOJ Longest Common Substring II相关的知识,希望对你有一定的参考价值。

Longest Common Substring II

Time Limit: 2000ms
Memory Limit: 262144KB

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

  这题是找一些字符串的最长公共子串。
  这里对其中一个建SAM,然后跑其他字符串,在每一个字符串中,记录SAM节点中每个节点对应的最长长度,最后在所有字符串中SAM的最长长度取MIN,答案最后再在对每个位置的最小值取MAX。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 struct SAM{
 7     int ch[200010][27],len[200010],fa[200010],last,cnt;
 8     void Init()
 9     {
10         memset(fa,0,sizeof(fa));
11         last=cnt=1;
12     }
13     void Insert(int c)
14     {
15         int p=last,np=last=++cnt;
16         len[np]=len[p]+1;
17         while(p&&!ch[p][c])
18             ch[p][c]=np,p=fa[p];
19         if(!p)
20             fa[np]=1;
21         else{
22             int q=ch[p][c];
23             if(len[p]+1==len[q])
24                 fa[np]=q;
25             else{
26                 int nq=++cnt;
27                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
28                 len[nq]=len[p]+1;
29                 fa[nq]=fa[q];
30                 fa[q]=fa[np]=nq;
31                 while(p&&ch[p][c]==q)
32                     ch[p][c]=nq,p=fa[p];
33             }    
34         }        
35     }
36 }sam;
37 char s[100010];
38 int ans[200010],f[200010];
39 int main()
40 {
41     memset(ans,127,sizeof(ans));
42     sam.Init();
43     scanf("%s",&s);
44     for(int i=0;s[i];i++)
45         sam.Insert(s[i]-a);    
46     while(~scanf("%s",s))
47     {
48         memset(f,0,sizeof(f));
49         int node=1,len=0;
50         for(int i=0;s[i];i++)
51         {
52             int c=s[i]-a;
53             while(node&&!sam.ch[node][c])
54                 node=sam.fa[node];
55             if(!node)
56                 node=1,len=0;
57             else
58                 len=sam.len[node]+1,node=sam.ch[node][c];
59             if(len>f[node])f[node]=len;            
60         }
61         for(int i=1;i<=sam.cnt;i++)
62             ans[i]=min(ans[i],f[i]);    
63     }
64     int ret=0;
65     for(int i=1;i<=sam.cnt;i++)
66         ret=max(ret,ans[i]);
67     printf("%d\n",ret);
68     return 0;
69 }

 


以上是关于后缀自动机(SAM):SPOJ Longest Common Substring II的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)两种做法

SPOJ 1811 Longest Common Substring

SPOJ 1812 Longest Common Substring II(后缀自动机)

SPOJ LCS Longest Common Substring(后缀自动机)题解

SPOJSubstrings(后缀自动机)

SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS