SPOJ1812 Longest Common Substring II
Longest Common Substring II
给定n个串,求它们的最长公共子串。
at most 10 lines,no more than 100000
iwt的题解
本题容易看出就是分别将所有串的所有匹配长度记录在状态上,然后取所有串记录值的min,后再对所有状态取max。
但是不要忘记了一点:更新parent树的祖先。
为什么呢?首先如果子树被匹配过了,那么长度一定大于任意祖先匹配的长度(甚至有些祖先匹配长度为0!为什么呢,因为我们在匹配的过程中,只是找到一个子串,可能还遗漏了祖先没有匹配到,这样导致了祖先的记录值为0,那么在对对应状态取min的时候会取到0,这样就wa了。而且注意,如果匹配到了当前节点,那么祖先们一定都可以赋值为祖先的length!因为当前节点的length大于任意祖先。(
比如数据
acbbc
bc
ac
答案应该是1没错吧。如果没有更新祖先,那么答案会成0。
这个多想想就行了。
所以以后记住:对任意多串匹配时,凡是对同一个状态取值时,要注意当前状态的子树是否比当前状态记录的值优。
时间复杂度:线性。
co int N=2e5;
namespace SAM
{
int tot,last;
int ch[N][26],fail[N]={-1},len[N];
void extend(int k)
{
int cur=++tot;
len[cur]=len[last]+1;
int p=last;
while(~p&&!ch[p][k])
{
ch[p][k]=cur;
p=fail[p];
}
if(p==-1)
fail[cur]=0;
else
{
int q=ch[p][k];
if(len[q]==len[p]+1)
fail[cur]=q;
else
{
int clone=++tot;
std::copy(ch[q],ch[q]+26,ch[clone]);
fail[clone]=fail[q],len[clone]=len[p]+1;
while(~p&&ch[p][k]==q)
{
ch[p][k]=clone;
p=fail[p];
}
fail[cur]=fail[q]=clone;
}
}
last=cur;
}
int c[N],id[N],mx[N],arr[N];
void build(char s[],int n)
{
for(int i=0;i<n;++i)
extend(s[i]-'a');
for(int i=0;i<=tot;++i)
++c[len[i]];
for(int i=1;i<=n;++i)
c[i]+=c[i-1];
for(int i=0;i<=tot;++i)
id[--c[len[i]]]=i; // edit 1:--c for 0
std::copy(len,len+tot+1,mx);
}
void find(char s[],int n)
{
int p=0,l=0;
for(int i=0;i<n;++i)
{
int k=s[i]-'a';
if(ch[p][k])
p=ch[p][k],++l;
else
{
while(~p&&!ch[p][k])
p=fail[p];
if(p==-1)
p=l=0;
else
l=len[p]+1,p=ch[p][k];
}
arr[p]=std::max(arr[p],l);
}
for(int i=tot;i>=0;--i)
{
int p=id[i];
mx[p]=std::min(mx[p],arr[p]);
if(arr[p]&&fail[p])
arr[fail[p]]=len[fail[p]];
arr[p]=0;
}
}
int getans()
{
int ans=0;
for(int i=0;i<=tot;++i)
ans=std::max(ans,mx[i]);
return ans;
}
}
char buf[N];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%s",buf);
SAM::build(buf,strlen(buf));
while(~scanf("%s",buf))
SAM::find(buf,strlen(buf));
printf("%d\n",SAM::getans());
return 0;
}
SPOJ1812 Longest Common Substring II的更多相关文章
- SPOJ1812 - Longest Common Substring II(LCS2)
Portal,Portal to 洛谷 Description 给出\(n(n\leq10)\)个仅包含小写字母的字符串\(s_1..s_n(|s_i|\leq10^5)\),求这些字符串的最长公共子 ...
- [SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串
题目链接:http://www.spoj.com/problems/LCS2/ 其实两个串的LCS会了,多个串的LCS也就差不多了. 我们先用一个串建立后缀自动机,然后其它的串在上面跑.跑的时候算出每 ...
- spoj1812 LCS2 - Longest Common Substring II
地址:http://www.spoj.com/problems/LCS2/ 题面: LCS2 - Longest Common Substring II no tags A string is fi ...
- SPOJ1812 LCS2 - Longest Common Substring II【SAM LCS】
LCS2 - Longest Common Substring II 多个字符串找最长公共子串 以其中一个串建\(SAM\),然后用其他串一个个去匹配,每次的匹配方式和两个串找\(LCS\)一样,就是 ...
- SPOJ LCS2 - Longest Common Substring II
LCS2 - Longest Common Substring II A string is finite sequence of characters over a non-empty finite ...
- 后缀自动机(SAM):SPOJ Longest Common Substring II
Longest Common Substring II Time Limit: 2000ms Memory Limit: 262144KB A string is finite sequence of ...
- 【SPOJ】Longest Common Substring II (后缀自动机)
[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...
- 【SP1812】LCS2 - Longest Common Substring II
[SP1812]LCS2 - Longest Common Substring II 题面 洛谷 题解 你首先得会做这题. 然后就其实就很简单了, 你在每一个状态\(i\)打一个标记\(f[i]\)表 ...
- SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS
LCS2 - Longest Common Substring II no tags A string is finite sequence of characters over a non-emp ...
随机推荐
- Windows Server 2008 R2 FTP无法从外部访问的解决方法
在Windows Server 2008 R2中配置好FTP服务器后,可以在本机访问,但是无法从另一台电脑访问.原因就是在于防火墙没有配置好. 1.首先检查服务器管理器中的入站规则,确保已启用FTP服 ...
- 14.python模块之subprocess
我们几乎可以在任何操作系统上通过命令行指令与操作系统进行交互,比如Linux平台下的shell.那么我们如何通过Python来完成这些命令行指令的执行呢?另外,我们应该知道的是命令行指令的执行通常有两 ...
- mysql分库分表(一)
mysql分库分表 参考: https://blog.csdn.net/xlgen157387/article/details/53976153 https://blog.csdn.net/cleve ...
- nginx重新加载配置(不停服)
RT,改变配置想让它生效而不停止服务,如下两种方式都可以: 1) nginx -t; nginx -s reload2) nginx -t; kill -HUP
- win7 vmware虚拟机上网设置
1.上网方式设成HOST-ONLY 2.将主机的网络共享VMnet1(完成第一步设置后,VMware自动分配虚拟网络VMnet1) 3.win7下查看VMnet1网络ip 4.根据3查看的IP地址在v ...
- virtio guest side implementation: PCI, virtio device, virtio net and virtqueue
With the publishing of OASIS virtio specification version 1.0, virtio made another big step in becom ...
- LeetCode第[34]题(Java):Search for a Range
题目:搜索目标范围 难度:Medium 题目内容: Given an array of integers nums sorted in ascending order, find the starti ...
- centos下使用fdisk扩展分区容量大小
硬盘空间为20G,VMware增加磁盘大小,需要再增加10G空间 扩展完后,重启系统,再次使用fdisk -l查看,会发现硬盘空间变大了: 重新创建分区,调整分区信息 本次实验主要对/dev/sda4 ...
- za2
程序集?生成后 一个exe,一个dll. 也可以是一个项目. vs 快速生成字段的代码段快捷键,快速生成构造函数,生成普通方法结构的快捷键 ************************* ...
- java多线程学习三
本章主要学习线程的静态方法 1.先忙先看一段代码: public class MyThread3 implements Runnable { static { System.out.println(& ...