spoj 1811 LCS - Longest Common Substring (后缀自己主动机)
spoj 1811 LCS - Longest Common Substring
题意:
给出两个串S, T, 求最长公共子串。
限制:
|S|, |T| <= 1e5
思路:
dp O(n^2) 铁定超时
后缀数组 O(nlog(n)) 在spoj上没试过,感觉也会被卡掉
后缀自己主动机 O(n)
我们考虑用SAM读入字符串B;
令当前状态为s,同一时候最大匹配长度为len;
我们读入字符x。假设s有标号为x的边,那么s=trans(s,x),len = len+1;
否则我们找到s的第一个祖先a。它有标号为x的边。令s=trans(a,x),len=Max(a)+1;
假设没有这种祖先,那么令s=root,len=0;
在过程中更新状态的最大匹配长度。
详情參考clj论文
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 3 * 1e5;
char S[N], T[N]; struct SAM {
struct Node {
int fa, ch[27];
int val;
void init() {
fa = val = 0;
memset(ch, 0, sizeof(ch));
}
} node[2 * N]; int tot;
int new_node() {
node[++tot].init();
return tot;
} int root, last;
void init() {
tot = root = last = 1;
node[0].init();
node[1].init();
} void add(int x) {
int p = last;
int np = new_node(); node[np].val = node[p].val + 1;
while(p && node[p].ch[x] == 0){
node[p].ch[x] = np;
p = node[p].fa;
}
if(p == 0) node[np].fa = root;
else {
int q = node[p].ch[x];
if(node[p].val + 1 == node[q].val)
node[np].fa = q;
else {
int nq = new_node(); node[nq].val = node[p].val + 1;
memcpy(node[nq].ch, node[q].ch, sizeof(node[q].ch));
node[nq].fa = node[q].fa;
node[q].fa = node[np].fa = nq;
while(p && node[p].ch[x] == q) {
node[p].ch[x] = nq;
p = node[p].fa;
}
}
}
last = np;
}
void debug() {
for(int i = 1; i <= tot; ++i) {
printf("id=%d, fa=%d, step=%d, ch=[ ", i, node[i].fa, node[i].val);
for(int j = 0; j < 26; ++j) {
if(node[i].ch[j])
printf("%c,%d ", j+'a', node[i].ch[j]);
}
puts("]");
}
} void gao();
} sam; void SAM::gao() {
int len_s = strlen(S);
int len_t = strlen(T); init();
for(int i = 0; i < len_s; ++i) {
add(S[i] - 'a');
}
//debug();
int p = root;
int ans = 0;
int tmp = 0;
for(int i = 0; i < len_t; ++i) {
if(node[p].ch[T[i] - 'a']) {
++tmp;
p = node[p].ch[T[i] - 'a'];
} else {
while(p && node[p].ch[T[i] - 'a'] == 0)
p = node[p].fa;
if(p) {
tmp = node[p].val + 1;
p = node[p].ch[T[i] - 'a'];
} else {
p = root;
tmp = 0;
}
}
ans = max(ans, tmp);
}
printf("%d\n", ans);
} int main() {
scanf("%s%s", S, T);
sam.gao();
return 0;
}
spoj 1811 LCS - Longest Common Substring (后缀自己主动机)的更多相关文章
- SPOJ 1811 LCS - Longest Common Substring
思路 和SPOJ 1812 LCS2 - Longest Common Substring II一个思路,改成两个串就有双倍经验了 代码 #include <cstdio> #includ ...
- 【刷题】SPOJ 1811 LCS - Longest Common Substring
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
- SPOJ1811 LCS - Longest Common Substring(后缀自动机)
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
- 后缀自动机(SAM) :SPOJ LCS - Longest Common Substring
LCS - Longest Common Substring no tags A string is finite sequence of characters over a non-empty f ...
- spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)
spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 < ...
- spoj1811 LCS - Longest Common Substring
地址:http://www.spoj.com/problems/LCS/ 题面: LCS - Longest Common Substring no tags A string is finite ...
- 【SP1811】LCS - Longest Common Substring
[SP1811]LCS - Longest Common Substring 题面 洛谷 题解 建好后缀自动机后从初始状态沿着现在的边匹配, 如果失配则跳它的后缀链接,因为你跳后缀链接到达的\(End ...
- SPOJ 10570 LONGCS - Longest Common Substring
思路 和SPOJ 1812 LCS2 - Longest Common Substring II一个思路,改成多组数据就有三倍经验了 代码 #include <cstdio> #inclu ...
- SPOJ LCS Longest Common Substring 和 LG3804 【模板】后缀自动机
Longest Common Substring 给两个串A和B,求这两个串的最长公共子串. no more than 250000 分析 参照OI wiki. 给定两个字符串 S 和 T ,求出最长 ...
随机推荐
- 第五部分 linux 软件安装RPM SRPM与YUM
第五部分 linux 软件安装RPM SRPM与YUM 软件管理员简介 RPM与DPKG两大主流 rpm: redhat centos suse 命令:yum ...
- Nginx报 No input file specified. 的问题解决之路 转
https://m.aliyun.com/yunqi/articles/34240 今天接手公司的一个项目,照例将项目clone下来,配置本地host,nginx,然后访问. 怎么回事?迅速在php的 ...
- 性能学习之六---socket接口测试
socket协议较底层,所以是一个万能协议.socket发的是数据包,所以较难看懂. 下面我们来讲解socket接口测试. 大致思路为:新建sever端和client端---建立连接---发送数据 一 ...
- kb-01-e<取余操作,宽搜,巧妙>;
题目描述: n属于1到200,找到对应的一个数只含有0和1,并且是n的倍数: 分析: 本题有几个数会是大数:所以要考虑大数: 用到余数的性质:例如n=6,1%6=1: 1*10%6=4: ...
- animation总结
1. animation结束后停在最后一帧 animation-fill-mode : forwards | both; /* 或者 */ animation: anim1 1s linear for ...
- [暑假集训--数位dp]UESTC250 windy数
windy定义了一种windy数. 不含前导零且相邻两个数字之差至少为22 的正整数被称为windy数. windy想知道,在AA 和BB 之间,包括AA 和BB ,总共有多少个windy数? Inp ...
- Idea连接服务器docker并部署代码到docker实现一键启动
好记性不如烂笔头,写笔记是为了回头看的. 谁要是不小心搜了看了,如有不足之处敬请谅解. 一.准备工作 虚拟机centos7.X,docker1.3.X,Win10 Idea2018.1 默认Idea已 ...
- 【CF713C】Sonya and Problem Wihtout a Legend(离散化,DP)
题意:给你一个数列,对于每个数字你都可以++或者−− 然后花费就是你修改后和原数字的差值,然后问你修改成一个严格递增的,最小花费 思路:很久以前做过一道一模一样的 严格递增很难处理,就转化为非严格递增 ...
- gridview中的相关事件操作
原文发布时间为:2008-07-27 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...
- [LeetCode] Text Justification words显示的排序控制
Given an array of words and a length L, format the text such that each line has exactly L characters ...