SPOJ LCS - Longest Common Substring 字符串 SAM
原文链接http://www.cnblogs.com/zhouzhendong/p/8982392.html
题目传送门 - SPOJ LCS
题意
求两个字符串的最长公共连续子串长度。
字符串长$\leq 250000$
题解
首先对于第一个字符串建一个$SAM$。
然后拿第二个串在$SAM$上面走一遍就好了。
具体地:
将第二个串的字符一个一个地按照顺序加入。
设当前状态为$now$,要加入字符$c$,当前匹配的字符串长度为$len$(答案自然是各种情况下$len$的最大值)。
如果在$SAM$上面,状态$now$有标号为$c$的转移,那么,$len=len+1$,$now$更新为转移后的结果。
否则,我们跳$now$的$fa$,直到得到一个新的$now$使得$now$有标号为$c$的转移,并使$len=Max(now)+1$,$now$更新为新的$now$再走$c$转移之后的状态。
关于上述做法的正确性的叙述:
对于第一种情况,相当于在原结果的末尾再加上一个匹配的字符。
对于第二种情况,略微复杂一些。首先,跳$fa$的效果其实就是从当前子串中删除前缀,直到匹配串$SAM$的当前状态再一次和被匹配串的当前子串相匹配。注意,由于状态$now$没有标号为$c$的转移,所以被匹配串的之前成功匹配的子串中,有一段前缀现在不能匹配了。所以你找到的第一个有标号为$c$的转移的$now$的祖先的$Max$值必然小于原来的$len$,所以在本次操作之后,新的$len$的值必然不大于原来的$len$。
UPD(2018-05-07): 这个第二种情况也可以通过分析后缀自动机性质来理解。这里不展开介绍。
首先,很显然这个匹配是成功的。又由于我们每次跳$fa$时候,保留的串长又是尽量长的,所以满足了最大化的要求。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=500005;
int n,last=1,size=1;
char s[N];
struct SAM{
int Next[26],fa,Max;
}t[N];
void expend(int c){
int p=last,np=++size,q,nq;
t[np].Max=t[p].Max+1;
for (;!t[p].Next[c];p=t[p].fa)
t[p].Next[c]=np;
q=t[p].Next[c];
if (t[q].Max==t[p].Max+1)
t[np].fa=q;
else {
nq=++size;
t[nq]=t[q],t[nq].Max=t[p].Max+1;
t[q].fa=t[np].fa=nq;
for (;t[p].Next[c]==q;p=t[p].fa)
t[p].Next[c]=nq;
}
last=np;
}
int main(){
t[0].Max=-1;
for (int i=0;i<26;i++)
t[0].Next[i]=1;
scanf("%s",s);
n=strlen(s);
for (int i=0;i<n;i++)
expend(s[i]-'a');
int ans=0;
scanf("%s",s);
n=strlen(s);
for (int i=0,now=1,len=0;i<n;i++){
int c=s[i]-'a';
if (t[now].Next[c]){
now=t[now].Next[c];
ans=max(ans,++len);
continue;
}
while (!t[now].Next[c])
now=t[now].fa;
ans=max(ans,len=t[now].Max+1);
now=t[now].Next[c];
}
printf("%d",ans);
return 0;
}
SPOJ LCS - Longest Common Substring 字符串 SAM的更多相关文章
- 后缀自动机(SAM) :SPOJ LCS - Longest Common Substring
LCS - Longest Common Substring no tags A string is finite sequence of characters over a non-empty f ...
- LCS - Longest Common Substring(spoj1811) (sam(后缀自动机)+LCS)
A string is finite sequence of characters over a non-empty finite set \(\sum\). In this problem, \(\ ...
- SPOJ LCS Longest Common Substring 和 LG3804 【模板】后缀自动机
Longest Common Substring 给两个串A和B,求这两个串的最长公共子串. no more than 250000 分析 参照OI wiki. 给定两个字符串 S 和 T ,求出最长 ...
- spoj LCS2 - Longest Common Substring II && LCS - Longest Common Substring【SAM】
多串LCS很适合SA但是我要学SAM 对第一个串求SAM,然后把剩下的串在SAM上跑,也就是维护p和len,到一个点,如果有ch[p][c],就p=ch[p][c],len++,否则向fa找最下的有c ...
- SPOJ LCS Longest Common Substring(后缀自动机)题解
题意: 求两个串的最大\(LCS\). 思路: 把第一个串建后缀自动机,第二个串跑后缀自动机,如果一个节点失配了,那么往父节点跑,期间更新答案即可. 代码: #include<set> # ...
- 【SP1811】 LCS - Longest Common Substring(SAM)
传送门 洛谷 Solution 考虑他要求的是最长公共子串对吧,那么我们对于一个串建后缀自动机,另一个串在后缀自动机上面跑就是了. 复杂度\(O(n+m)\)的,很棒! 代码实现 代码戳这里
- spoj 1811 LCS - Longest Common Substring (后缀自己主动机)
spoj 1811 LCS - Longest Common Substring 题意: 给出两个串S, T, 求最长公共子串. 限制: |S|, |T| <= 1e5 思路: dp O(n^2 ...
- spoj1811 LCS - Longest Common Substring
地址:http://www.spoj.com/problems/LCS/ 题面: LCS - Longest Common Substring no tags A string is finite ...
- 【SPOJ】Longest Common Substring II
[SPOJ]Longest Common Substring II 多个字符串求最长公共子串 还是将一个子串建SAM,其他字符串全部跑一边,记录每个点的最大贡献 由于是所有串,要对每个点每个字符串跑完 ...
随机推荐
- Linux 操作系统死机故障处理方法总结
通常在出现系统崩溃后,大家会担心再次出现故障,但是发现系统各日志中并没有记录到任何死机前后的信息,无法分析故障原因,认为已经无药可救.但是,实际上,Linux 有多种机制来保证发生系统崩溃后,可以获取 ...
- vuforia unity 识别图片出模型
ARCamera设置: 然后设置ImageTarge
- Confluence 6 整合到其他数据库
这个文档描述了如何整合你的 Confluence 数据库从你已经存在的数据库上到其他的数据库.这个指南被用来指导你从使用评估数据库转移到使用生产数据库. 大数据量需要第三方的数据库整合工具. 本页面对 ...
- 基于vue-cli3的vue项目移动端样式适配,lib-flexible和postcss-px2rem
1,安装 flexible和 postcss-px2rem(命令行安装) npm install lib-flexible --save npm install postcss-px2rem --sa ...
- python之线程同步
lock与rlock 使用lock不能连续两次获取锁,获取锁必须先释放锁.但是在一个线程中调用另一个函数时,在该函数中要继续操作共享的数据,这时获取锁就相当于连续执行两次获取锁,所以lock就不适用该 ...
- mac 端口占用问题
查看端口号 终端输入:sudo lsof -i tcp:port 将port换成被占用的端口(如:8086.9998) 将会出现占用端口的进程信息. 杀死占用端口的PID进程 找到进程的PID,使用k ...
- linq2db.EntityFrameworkCore 介绍
linq2db.EntityFrameworkCore 是一个ef core的插件,对linq语法的扩展 对复杂的sql都有很好的支持,他是基于linq2db (provided by LINQ To ...
- 断路器Ribbon
断路器:就是对服务访问不到的情况做出自己的错误,也就是故障转移(将当前出现故障的请求重新返回特定消息) 改造消费者项目(RibbonDemo) 1.在pom.xml中引入hystrix的jar包 &l ...
- mysql老是停止运行该怎么解决
你可能还会遇到无法启动mysql的错误 解决方法如下:
- strchr()
strchr()主要有2个最有用的用法: 第一个:搜索字符串在另一字符串中的第一次出现.并返回剩余的部分 $str = "hello_chrdai_1993"; $not_incl ...