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

LCS - Longest Common Substring

no tags

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 simple, for two 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 exactly two lines, each line consists of no more than 250000 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

Output:
3

  这题就是求最长公共子串,于是我直接套用了SAM。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int MAXN=1000010;
 6 struct SAM{
 7     int fa[MAXN],ch[MAXN][27],len[MAXN],cnt,last;
 8     void Init()
 9     {
10         last=cnt=1;
11     }
12     void Insert(int c)
13     {
14         int p=last,np=last=++cnt;
15         len[np]=len[p]+1;
16         while(!ch[p][c]&&p)
17             ch[p][c]=np,p=fa[p];
18         if(!p)fa[np]=1;
19         else{
20             int q=ch[p][c];
21             if(len[q]==len[p]+1)
22                 fa[np]=q;
23             else{
24                 int nq=++cnt;len[nq]=len[p]+1;
25                 memcpy(ch[nq],ch[q],sizeof(ch[p]));
26                 fa[nq]=fa[q];fa[q]=fa[np]=nq;
27                 while(ch[p][c]==q)
28                     ch[p][c]=nq,p=fa[p];
29             }
30         }
31     }
32 }sam;
33 char str1[MAXN],str2[MAXN];
34 int main()
35 {
36     int len1=0,len2=0,ans=0;
37     scanf("%s%s",str1,str2);
38     sam.Init();
39     while(str1[len1])
40         sam.Insert(str1[len1++]-‘`‘);
41     int node=1,tmp=0;
42     for(;str2[len2];len2++){
43         int c=str2[len2]-‘`‘;
44         if(sam.ch[node][c])
45             node=sam.ch[node][c],tmp++;
46         else{
47             while(node&&!sam.ch[node][c])
48                 node=sam.fa[node];
49             if(node==0)
50                 node=1,tmp=0;
51             else
52                 tmp=sam.len[node]+1,node=sam.ch[node][c];
53         }
54         ans=max(ans,tmp);
55     }
56     printf("%d\n",ans);
57     return 0;
58 }
时间: 2024-10-21 09:12:01

后缀自动机(SAM) :SPOJ LCS - Longest Common Substring的相关文章

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

题意: 求两个串的最大\(LCS\). 思路: 把第一个串建后缀自动机,第二个串跑后缀自动机,如果一个节点失配了,那么往父节点跑,期间更新答案即可. 代码: #include<set> #include<map> #include<cmath> #include<queue> #include<bitset> #include<string> #include<cstdio> #include<vector>

spoj 1811 LCS - Longest Common Substring (后缀自动机)

spoj 1811 LCS - Longest Common Substring 题意: 给出两个串S, T, 求最长公共子串. 限制: |S|, |T| <= 1e5 思路: dp O(n^2) 铁定超时 后缀数组 O(nlog(n)) 在spoj上没试过,感觉也会被卡掉 后缀自动机 O(n) 我们考虑用SAM读入字符串B; 令当前状态为s,同时最大匹配长度为len; 我们读入字符x.如果s有标号为x的边,那么s=trans(s,x),len = len+1; 否则我们找到s的第一个祖先a,它

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

[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记录\(f[i]\)表示走到了\(i\)节点 能够匹配上的最长公共子串的长度 当然,每个串的\(f[i]\)可以更新\(f[i.parent]\) 所以需要拓扑排序 对于每个串求出每个节点的最长匹配 然后对他们取\(min\),表示某个节点大家都能匹配的最长长度 最后对于所有点的值都取个\(max\)

【SPOJ】Longest Common Substring(后缀自动机)

[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另外一个串在\(SAM\)上不断匹配 最后计算答案就好了 匹配方法: 如果\(trans(s,c)\)存在 直接沿着\(trans\)走就行,同时\(cnt++\) 否则沿着\(parent\)往上跳 如果存在\(trans(now,c),cnt=now.longest+1\) 否则,如果不存在可行的

SPOJ 1811LCS Longest Common Substring

后缀自动机裸题.... Longest Common Substring Time Limit: 2000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is

【SPOJ】Longest Common Substring

[SPOJ]Longest Common Substring 求两个字符串的最长公共子串 对一个串建好后缀自动机然后暴力跑一下 废话 讲一下怎么跑吧 从第一个字符开始遍历,遍历不到了再沿着\(parents\)走看能否找到出路,走到某个点时,统计一下走过了多少点然后更新答案 来说说这样做的正确性: 遍历是肯定的, PAM 从根节点出发的任意路径都表示一个子串 沿着\(parents\)边往后走,保证贪心情况下维护最长公共子串寻找出路 注意这里是统计走过了多少点更新答案,不能直接通过\(len\)

【SPOJ】Longest Common Substring II

[SPOJ]Longest Common Substring II 多个字符串求最长公共子串 还是将一个子串建SAM,其他字符串全部跑一边,记录每个点的最大贡献 由于是所有串,要对每个点每个字符串跑完后去最小值才是每个点的最终贡献 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm

【刷题】SPOJ 1811 LCS - Longest Common Substring

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 i

Spoj LCS2 - Longest Common Substring II

题目描述 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 t