#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 500005
#define maxl 250005
using namespace std; int n,m,ans,last,len,tot,root,son[maxn][],fa[maxn],dist[maxn];
char s1[maxl],s2[maxl];
struct Tsegment{
void prepare(){last=tot=root=;}
int newnode(int x){dist[++tot]=x;return tot;}
void add(int x){
int p=last,np=newnode(dist[p]+); last=np;
for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
if (p==) fa[np]=root;
else{
int q=son[p][x];
if (dist[p]+==dist[q]) fa[np]=q;
else{
int nq=newnode(dist[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q],fa[q]=fa[np]=nq;
for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
}
}
}
}SAM;
int main(){
scanf("%s",s1+),n=strlen(s1+);
scanf("%s",s2+),m=strlen(s2+);
SAM.prepare();
for (int i=;i<=n;i++) SAM.add(s1[i]-'a');
ans=,len=,last=root;
for (int i=;i<=m;i++){
int x=s2[i]-'a';
if (son[last][x]) len++,last=son[last][x];
else{
for (;last&&!son[last][x];) last=fa[last];
if (last==) len=,last=root;
else{
len=dist[last]+,last=son[last][x];
}
}
ans=max(ans,len);
}
printf("%d\n",ans);
return ;
}

题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=2796

题目大意:给定两个字符串,长度<=2.5*10^5,询问这两个字符串的最长公共子串的长度,这题以前用后缀数组写过,比较基础,这次是用SAM写的,比较坑爹。

做法:最近学习了后缀自动机,讲讲我的理解:

后缀自动机可以识别一个字符串中的所有子串,写过AC自动机的同学都知道Trie树,如果按照那种方法建树的话,空间复杂度为n^2,但是我们发现有很多重复的状态,我们会发现,有很多个子串的右端点集合完全相同,那么这些字符串向后匹配的能力是相同的,故可将其缩成一个状态。

我先介绍几个性质:

1.right集合要么没有交集,要么真包含,用反证法易得。

2.对于某一个right集合中字符串,其长度有一个区间,即为【min,max】,若大于这个长度区间,|right|会减小,反之增大。

3.由于性质1,我们可以发现利用right集合能建立一棵树,满足:父亲的right集合是真包含儿子节点right集合中max最大的 ,且满足父亲的max+1=儿子的min。这三条性质在建立后缀自动机的时候有用。

如何建立后缀自动机呢?

建立过程比较麻烦,大家画个图理解理解吧,orzclj……

具体看代码。。。。。细节太多。。

这于这题的做法:

对第一个字符串建立SAM,第二个字符串在SAM上匹配即可,若失配,就跳fa,因为fa的right集合真包含于自己的right集合,这样缩短字符串长度,却能增加后续匹配的可能性,及时更新答案即可。

后缀自动机。

spoj1811 Longest Common Substring的更多相关文章

  1. [SPOJ1811]Longest Common Substring 后缀自动机 最长公共子串

    题目链接:http://www.spoj.com/problems/LCS/ 题意如题目,求两个串的最大公共子串LCS. 首先对其中一个字符串A建立SAM,然后用另一个字符串B在上面跑. 用一个变量L ...

  2. SPOJ1811 LCS - Longest Common Substring(后缀自动机)

    A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...

  3. LCS - Longest Common Substring(spoj1811) (sam(后缀自动机)+LCS)

    A string is finite sequence of characters over a non-empty finite set \(\sum\). In this problem, \(\ ...

  4. spoj1811 LCS - Longest Common Substring

    地址:http://www.spoj.com/problems/LCS/ 题面: LCS - Longest Common Substring no tags  A string is finite ...

  5. SPOJ LCS2 - Longest Common Substring II

    LCS2 - Longest Common Substring II A string is finite sequence of characters over a non-empty finite ...

  6. LintCode Longest Common Substring

    原题链接在这里:http://www.lintcode.com/en/problem/longest-common-substring/# 题目: Given two strings, find th ...

  7. Longest Common Substring

    Given two strings, find the longest common substring. Return the length of it. Example Given A = &qu ...

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

    http://www.spoj.com/problems/LCS2/ 发现了我原来对sam的理解的一个坑233 本题容易看出就是将所有匹配长度记录在状态上然后取min后再对所有状态取max. 但是不要 ...

  9. hdu 1403 Longest Common Substring(最长公共子字符串)(后缀数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=1403 Longest Common Substring Time Limit: 8000/4000 MS (Ja ...

随机推荐

  1. repeater 根据输入 返回汉字

    page repeater <asp:Repeater ID="r_scoreCount" runat="server"> <HeaderTe ...

  2. .net混淆、反编译工具调查

    常用的工具列表[比较常见的] 混淆器.加密 Dotfuscator VS默认带的工具,不过是个社区版 强度不大 dotNET Reactor 使用了NativeCode 和混淆的形式 Xenocode ...

  3. Alpha版本发布说明

    软件发布的同时,在团队博客上写一个发布说明     ▪ 列出这一版本的新功能     ▪ 这一版本修复的缺陷     ▪ 对运行环境的要求     ▪ 安装方法     ▪ 描述系统已知的问题和限制 ...

  4. sqlserver数据库附加分离备份还原命令

    --获取所有数据库的名称 select [name] from master.dbo.sysdatabases where [name]='master' --判断数据库是否存在 if exists( ...

  5. DOM 元素节点几何量与滚动几何量

    当在 Web 浏览器中查看 HTML 文档时,DOM 节点被解析,并被渲染成盒模型(如下图),有时我们需要知道一些信息,比如盒模型的大小,盒模型在浏览器中的位置等等,本文我们就来详细了解下元素节点的几 ...

  6. 初用protobuf-csharp-port

    下面这个用法是参照protobuf-csharp-port的官方wiki,参见: https://code.google.com/p/protobuf-csharp-port/wiki/Getting ...

  7. Hotspot内存溢出测试

    一.堆溢出 在执行代码时通过设置堆的最小值-Mms以及堆的最大值-Mmx来控制堆的大小,-XX参数dump出堆内存快照以便对内存溢出进行分析.通过创建大量对象来使堆溢出,当堆内存溢出时会提示OutOf ...

  8. eclipse的历史版本及下载

    有时候我们总会遇到在需要eclipse而无法及时找到的时候, 所以那些有用的链接, 是帮助我们能够及时找到我们想要版本的额最好方式 Eclipse 3.1 IO[木卫一,伊奥] 2005 http:/ ...

  9. kill 根据PID终止进程

    根据PID终止进程 kill [option] PID-list kill 通过向一个或多个进程发送信号来终止进程.除超级用户外,只有进程的所有者才可以对进程执行kill 参数 PID-list为ki ...

  10. C#分割字符串

    命名空间:System.String.Split 程序集:mscorlib( mscorlib.dll) 简单实例: string before = "12,50,30"; str ...