Longest Common Substring SPOJ - LCS (后缀自动机)
Longest Common Substring
\]
题意
给出两个串,求两个串的最长公共连续子序列的长度,两个串的长度小于等于250000。
思路
先对第一个串构建后缀自动机,根据后缀自动机的性质,从 \(root\) 的所有路径都是原串中的子串,又因为构建的时候,我们用 \(node[i].len\) 表示与节点 \(i\) 的 \(endpos\) 相同的所有子串集合的最长长度,那么我们就可以在后缀自动机上一次添加一个字符的去查询 \(res\) ,然后最大的 \(res\) 就是最后的答案。
在后缀自动机上查询的时候,我们用两个变量来更新答案,\(p\) 表示现在在后缀自动机上的状态,\(res\) 表示目前的最长公共连续长度。
- 如果对于下一个字符 \(k\) ,现在的 \(p\) 有这样的一条边,那么直接更新 \(p\),并且 \(res\)++。
- 如果没有这样的一条边,那么就从 \(p\) 跳到 \(node[i].fa\) 的位置,一直跳到有 \(k\) 的一条边为止停下或者走完整个后缀自动机。
- 如果跳到结束也没有找到 \(k\) 边,那么就让 \(p\) 变回 \(root\),\(res=0\)。
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 3e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
struct SAM {
struct Node{
int next[27];
int fa, len;
void init() {
mes(next, 0);
fa = len = 0;
}
} node[maxn<<1];
int sz, last;
void init() {
sz = last = 1;
node[sz].init();
}
void insert(int k) {
int p = last, np = last = ++sz;
node[np].init();
node[np].len = node[p].len+1;
for(; p && !node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p==0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len + 1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len+1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
int solve(char *s) {
int len = strlen(s+1);
int res = 0, p = 1, ans = 0;
for(int i=1; i<=len; i++) {
int k = s[i]-'a'+1;
while(p && !node[p].next[k]) {
p = node[p].fa;
res = node[p].len;
}
if(!p) {
p = 1;
res = 0;
} else {
p = node[p].next[k];
res++;
}
ans = max(ans, res);
}
return ans;
}
} sam;
char s[maxn], t[maxn];
int main() {
scanf("%s%s", s+1, t+1);
sam.init();
int len = strlen(s+1);
for(int i=1; i<=len; i++) {
sam.insert(s[i]-'a'+1);
}
int ans = sam.solve(t);
printf("%d\n", ans);
return 0;
}
Longest Common Substring SPOJ - LCS (后缀自动机)的更多相关文章
- 【SPOJ】Longest Common Substring II (后缀自动机)
[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...
- SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
- 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】1812. Longest Common Substring II(后缀自动机)
http://www.spoj.com/problems/LCS2/ 发现了我原来对sam的理解的一个坑233 本题容易看出就是将所有匹配长度记录在状态上然后取min后再对所有状态取max. 但是不要 ...
- SPOJ 1812 Longest Common Substring II(后缀自动机)
[题目链接] http://www.spoj.com/problems/LCS2/ [题目大意] 求n个串的最长公共子串 [题解] 对一个串建立后缀自动机,剩余的串在上面跑,保存匹配每个状态的最小值, ...
- SPOJ - LCS2 Longest Common Substring II(后缀自动机)题解
题意: 求\(n\)个串的最大\(LCS\). 思路: 把第一个串建后缀自动机,然后枚举所有串.对于每个串,求出这个串在\(i\)节点的最大匹配为\(temp[i]\)(当前串在这个节点最多取多少), ...
- 2018.12.15 spoj Longest Common Substring II(后缀自动机)
传送门 后缀自动机基础题. 给出10个串求最长公共子串. 我们对其中一个建一个samsamsam,然后用剩下九个去更新范围即可. 代码: #include<bits/stdc++.h> # ...
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...
- SPOJ - LCS 后缀自动机入门
LCS - Longest Common Substring A string is finite sequence of characters over a non-empty finite set ...
随机推荐
- maven 引入qrcode.jar
mvn install:install-file -Dfile=e:\QRCode.jar -DgroupId=QRCode -DartifactId=QRCode -Dversion=3.0 ...
- Java基础知识点总结(一)
1.源文件声明规则2.JAVA基本类型void3.数据类型默认值4.自动类型转换5.Java变量类型6.Java局部变量7.访问控制修饰符8.父类与子类的访问控制9.instanceof运算符 1.源 ...
- excel 使用
列于列拼接
- 【题解】【网络流24题】汽车加油行驶问题 [P4009] [Loj6223]
[题解][网络流24题]汽车加油行驶问题 [P4009] [Loj6223] 传送门:汽车加油行驶问题 \([P4009]\) \([Loj6223]\) [题目描述] 给出一个 \(N \times ...
- java学习:循环结构的使用规则和注意事项
循环结构的基本组成部分,一般可分为四部分: 初始化语句:在循环开始最初执行,而且只做唯一一次 条件判断:如果成立,则循环继续:如果不成立,则循环退出. 循环体:重复要做的事情内容,若干行语句. 进步语 ...
- PriorityQueue详解
美人如斯!好好看文章! 前言 java中关于Queue队列的实现繁多(关于Queue可以移步至我的另一篇文章:<Queue介绍>),每种实现根据自身的特性都有相应的应用场景.这里我们就来聊 ...
- TeamViewer14试用版到期-怎么解决
Teamviewer14提示试用期已到期怎么办? 问题分析: 出现这种问题,是因为在安装是选择了[公司/商务用途]或者[以上都是]这两个选项中的一个 解决方法: 1.退出TeamViewer远程软件, ...
- vim中常用折叠命令
最常用3个折叠命令 .反复打开关闭折叠:za (意思就是,当光标处折叠处于打开状态,za关闭之,当光标处折叠关闭状态,打开之) .打开全部折叠:zR .关闭全部折叠:zM 小试折叠: :set fdm ...
- CentOS 7 安装 mysql 5.7.27 for zabbix
本文是因为需要安装zabbix系统,才贴出的此步骤,供自己查阅方便之用: 在安装使用zabbix前,需要先安装数据库,这里使用的是MySQL数据库进行部署,给出安装步骤,大家觉得有用也可收藏: 当然安 ...
- javascript 对象之hasOwnProperty()方法
hasOwnProperty()方法是判断某一个对象是否有你给出的属性名称,需要注意的是该方法无法检测该对象原型连中是否具有该属性 具体格式下: var person = {"name&qu ...