【SAM】codevs3160-最长公共子串
【题目大意】
求两个字符串的最长公共子串。
【思路】
对第一个字符串建立后缀自动机,第二个字符串去匹配。cnt记录当前最长公共子串的长度,而ret记录答案。
p代表位置指针,初始在rt位置。
对于第二个字符串的某一位s[i],如果当前有s[i]孩子,则cnt+1,继续往后移动;否则沿着pre指针返回。如果pre指针返回到0,则将p回到rt,cnt清空为0;否则如果中间有点拥有s[i]孩子,cnt=step[]+1。
为什么cnt=step[]+1?不要忘了后缀自动机的本质是维护后缀,沿着pre指针跑就是往长度更小的后缀移动,某位置代表的后缀的最长长度为step[],再加上s[i],即是step[]+1。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN=+;
int n;
char str[][MAXN];
struct SAM
{
int step[MAXN*],pre[MAXN*],next[MAXN*][];
int tot,last;
inline int newNode(int cnt)
{
step[++tot]=cnt;
pre[tot]=;
for (int i=;i<;i++) next[tot][i]=;
return tot;
} inline void extend(int x)
{
int p=last;
int np=newNode(step[p]+);
while (p && !next[p][x]) next[p][x]=np,p=pre[p];
if (!p) pre[np]=;
else
{
int q=next[p][x];
if (step[q]==step[p]+) pre[np]=q;
else
{
int nq=newNode(step[p]+);
for (int i=;i<;i++) next[nq][i]=next[q][i];
pre[nq]=pre[q];
pre[q]=pre[np]=nq;
while (p&&next[p][x]==q) next[p][x]=nq,p=pre[p];
} }
last=np;
} inline void clear()
{
int tot=;
last=newNode(tot);
} inline int Query()
{
int ret=,cnt=;
int p=;
for(int i=;str[][i];i++)
{
int index=str[][i]-'a';
if(next[p][index]) p=next[p][index],cnt++;
else
{
while (p && !next[p][index]) p=pre[p];
if(!p) p=,cnt=;
else cnt=step[p]+,p=next[p][index];
/*由于沿着pre返回得到的字符串是当前字符串的后缀,所以第一个拥有index孩子的就是最长满足的后缀,长度即为step+1*/
}
ret=max(ret,cnt);
}
return ret;
}
}suf; void init()
{
scanf("%d",&n);
scanf("%s",str[]);
int len=strlen(str[]);
suf.clear();
for (int i=;i<len;i++) suf.extend(str[][i]-'a');
scanf("%s",str[]);
} int main()
{
init();
printf("%d",suf.Query());
return ;
}
【SAM】codevs3160-最长公共子串的更多相关文章
- [codevs3160]最长公共子串解题报告|后缀自动机
给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 样例就觉得不能更眼熟啊...好像之前用后缀数组做过一次 然后发现后缀自动机真的好好写啊...(当然当时学后缀数组的时候也这么认为... 这 ...
- 【文文殿下】后缀自动机(SAM)求最长公共子串的方法
首先,在A 串上建立一个SAM,然后用B串在上面跑.具体跑的方法是: 从根节点开始,建立一个指针 p ,指着B串的开头,同步移动指针,沿着SAM的边移动,如果可以移动(即存在边)那么万事皆好,直接le ...
- codevs3160 最长公共子串
传送门:http://codevs.cn/problem/3160/ [题解] CTSC前复习模板 sa的模板..记住基数排序就够了(还有height) 还有就是sa[i]表示排名为i的后缀是啥..r ...
- BZOJ 2946 POI2000 公共串 后缀自动机(多串最长公共子串)
题意概述:给出N个字符串,每个串的长度<=2000(雾...可能是当年的年代太久远机子太差了),问这N个字符串的最长公共子串长度为多少.(N<=5) 抛开数据结构,先想想朴素做法. 设计一 ...
- codevs 3160 最长公共子串(SAM)
3160 最长公共子串 题目描述 Description 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入描述 Input Description 读入两个字符串 输出描述 Ou ...
- 【codevs3160】最长公共子串 后缀数组
题目描述 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入 读入两个字符串 输出 输出最长公共子串的长度 样例输入 yeshowmuchiloveyoumydearmotherrea ...
- 【spoj2774】最长公共子串
题目描述: 给你两个字符串,求它们最长公共子串的长度,如果不存在公共子串则输出0. 样例输入: yeshowmuchiloveyoumydearmotherreallyicannotbelieveit ...
- SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)
题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...
- SCOJ 4493: DNA 最长公共子串 后缀自动机
4493: DNA 题目连接: http://acm.scu.edu.cn/soj/problem.action?id=4493 Description Deoxyribonucleic acid ( ...
随机推荐
- jQuery取值的一些奇奇怪怪的操作
语法解释:1. $("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发2. var ch ...
- js常用模板引擎
baiduTemplate(百度).artTemplate(腾讯).juicer(淘宝).xtemplate.doT.Jade 1.Handlebars 是 JavaScript 一个语义模板库,通过 ...
- Python 下调用C动态链接库 -- (转)
在linux开发的动态链接库需要被python调用,首先需要生成.so文件. 生成动态链接库的方法网上有很多,主要就是首先根据源文件编译生成.o,然后链接这些.o文件-shared生成.so.需要注意 ...
- adb端口被占用解决
解决ADB端口占用问题 方式一5037为adb默认端口,若5037端口被占用,查看占用端口的进程PIDC:\Users\wwx229495>netstat -aon|findstr 5037 ...
- Ribbon的主要组件与工作流程
一:Ribbon是什么? Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起.Ribbon客户端组件提供一系列完善的配置项如连接 ...
- 转 Wireshark和TcpDump抓包分析心得
1. Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Windows平台下使用Wireshark,如果是Linux的话 ...
- epoll内核源码分析
转载:https://www.nowcoder.com/discuss/26226?type=0&order=0&pos=27&page=1 /* * fs/eventpo ...
- FineReport——插入行策略
1.空值是默认的选项,即每次插入新行时,格子都是空白的. 2.原值即单元格中原有内容是什么,就复制到新增的格子中,一般适用于单元格是使用公式定义的, 在插入单元格时,公式会保留下来. 3.默认值即通过 ...
- C#面向对象(OOP)入门—第一天—多态和继承(方法重载)
面向对象是什么 面向对象是一种基于对象的编程方法,它取代了仅仅依靠方法和流程的编程方式.面向对象的编程语言中,对象(object)其实就是指特定类型.或某个类的实例.面向对象使得编程人员更容易组织和管 ...
- 关于指针pointer的位数与程序有关还是与系统有关、以及指针的指针的理解