SAM求多个串的最长公共子串
又学到一个\(SAM\)的新套路QvQ
思路
考虑用其中的一个串建个\(SAM\),然后用其他的串在上面匹配,匹配时更新答案
首先有一个全局变量\(len\),表示当前已匹配的长度。假设目前在点\(u\),转移方式如下(根节点为\(1\)):
如果没有对应的转移边,就走后缀连接,\(u=suflink(u)\),并令\(len=maxlen(suflink(u))\)。否则走对应的转移边,同时\(len++\)。如果一直没有对应的转移边,即到最后发现\(u=0\),就把\(u\)置为\(1\),\(len\)置为\(0\),并开始下个字符的匹配
开一个数组\(mx\)记录每个结点被匹配时的\(len\)最大是多少,全部匹配完后还要拓扑排序一遍,把每个结点的\(mx\)上传给其\(parent\ tree\)上的祖先。对于一个结点\(u\),它所代表的\(lcs\)长度为每个字符串匹配完后\(mx\)中的最小值,每次更新一下就行了
代码
#include <bits/stdc++.h>
using namespace std;
#define N 100000
int m, n, root = 1, nid = 1, last = 1, maxlen[2*N+5], ch[2*N+5][26], link[2*N+5], mx[2*N+5], mn[2*N+5], len;
int tmp[2*N+5], a[2*N+5];
void insert(int c) {
int cur = ++nid;
maxlen[cur] = maxlen[last]+1;
while(last && !ch[last][c]) ch[last][c] = cur, last = link[last];
if(!last) link[cur] = root;
else {
int p = last, q = ch[last][c];
if(maxlen[q] == maxlen[p]+1) link[cur] = q;
else {
int clone = ++nid;
maxlen[clone] = maxlen[p]+1;
for(int i = 0; i < 26; ++i) ch[clone][i] = ch[q][i];
link[clone] = link[q]; link[q] = link[cur] = clone;
while(p && ch[p][c] == q) ch[p][c] = clone, p = link[p];
}
}
last = cur;
}
void radixSort() {
memset(tmp, 0, sizeof tmp);
for(int i = 1; i <= nid; ++i) tmp[maxlen[i]]++;
for(int i = 1; i <= m; ++i) tmp[i] += tmp[i-1];
for(int i = 1; i <= nid; ++i) a[tmp[maxlen[i]]--] = i;
for(int i = nid; i >= 1; --i)
mx[link[a[i]]] = max(mx[link[a[i]]], min(maxlen[link[a[i]]], mx[a[i]])), mn[a[i]] = min(mn[a[i]], mx[a[i]]);
}
void calc(char *s) {
n = strlen(s);
memset(mx, 0, sizeof mx);
int u = root;
len = 0;
for(int i = 0; i < n; ++i) {
while(u && !ch[u][s[i]-'a']) u = link[u], len = maxlen[u];
if(!u) u = root;
else {
u = ch[u][s[i]-'a'];
len++;
mx[u] = max(mx[u], len);
}
}
radixSort();
}
int main() {
char s[N+5];
scanf("%s", s);
m = strlen(s);
for(int i = 0; i < m; ++i) insert(s[i]-'a');
memset(mn, 0x3f, sizeof mn);
while(~scanf("%s", s)) calc(s);
int ans = 0;
for(int i = 1; i <= nid; ++i) ans = max(ans, mn[i]);
printf("%d\n", ans);
return 0;
}
例题
SP1811
SP1812
SP10570
[SDOI2008]Sandy的卡片
SAM求多个串的最长公共子串的更多相关文章
- SPOJ 1811 Longest Common Substring(求两个串的最长公共子串 || 或者n个串)
http://www.spoj.com/problems/LCS/ 题目:求两个串的最长公共子串 参考:https://www.cnblogs.com/autoint/p/10345276.html: ...
- SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)
题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...
- 多个串的最长公共子串 SPOJ - LCS2 后缀自动机
题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...
- 【poj1226-出现或反转后出现在每个串的最长公共子串】后缀数组
题意:求n个串的最长公共子串,子串出现在一个串中可以是它的反转串出现.总长<=10^4. 题解: 对于每个串,把反转串也连进去.二分长度,分组,判断每个组. #include<cstdio ...
- SPOJ LCS2 多个串的最长公共子串
这里串最多有10个,找所有串的最长公共子串 这里后缀自动机做,以第一个串建立后缀自动机,后面的串一个个去匹配,每次得到当前串在可到达状态上所能得到的最长后缀长度 拿所有串匹配后得到的结果进行计算 #i ...
- 求两个字符串的最长公共子串——Java实现
要求:求两个字符串的最长公共子串,如“abcdefg”和“adefgwgeweg”的最长公共子串为“defg”(子串必须是连续的) public class Main03{ // 求解两个字符号的最长 ...
- [URAL-1517][求两个字符串的最长公共子串]
Freedom of Choice URAL - 1517 Background Before Albanian people could bear with the freedom of speec ...
- POJ 2774 求两个串的最长公共前缀 | 后缀数组
#include<cstdio> #include<algorithm> #include<cstring> #define N 200005 using name ...
- [SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串
题目链接:http://www.spoj.com/problems/LCS2/ 其实两个串的LCS会了,多个串的LCS也就差不多了. 我们先用一个串建立后缀自动机,然后其它的串在上面跑.跑的时候算出每 ...
随机推荐
- nginx系列7:处理HTTP请求的11个阶段
处理HTTP请求的11个阶段 如下图: 序号 阶段 指令 备注 1 POST_READ realip 获取客户端真实IP 2 SERVER_REWRITE rewrite 3 FIND_CONFIG ...
- vue 单文件组件中样式加载
在写单文件组件时,一般都是把标签.脚本.样式写到一起,这样写个人感觉有点不够简洁,所以就想着把样式分离出去. 采用import加载样式 在局部作用域(scoped)采用@import加载进来的样式文件 ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)
题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...
- 生鲜配送管理系统_升鲜宝V2.0 价格组功能 操作说明_15382353715
价格组功能是B端供应链系统,必不可少的一个功能,其主要实现不同的客户不同的价格,B端系统有一个最大的不同就是,有些商品后台下单人员能看到的.有些商品在销售的那一瞬间,还不知道价格.所以这些商品只有后台 ...
- iPhone手机怎么投影到MacPro上
https://www.bilibili.com/video/av27255821/ 2.使用Refletor,记得电脑和手机使用同一个wifi
- Android开发支付集成——支付宝集成
微信支付传送门:https://www.cnblogs.com/dingxiansen/p/9209159.html 一.支付宝支付 1. 支付宝支付流程图 2. 集成前准备 去蚂蚁金服注册应用获取a ...
- packagereference 里面的资产是怎么回事?
<PackageReference Include="Newtonsoft.Json" Version="9.0.1"> <ExcludeAs ...
- Ubuntu 服务器443端口证书配置
配置虚拟主机: cd /etc/apache2/sites-available 从默认的模板文件中复制过来一份进行自己的配置: sudo cp ./default-ssl.conf ./mysite1 ...
- Mac10.12下Python3.4调用oracle
最近,由于项目的短信平台对其它浏览器兼容,只支持IE,但是我们移动端自动化需要测试iphone手机,必须要连接MAC系统下,众所周知,MAC对IE的不友好性,故没办法通过短信平台在UI层自动化获取短信 ...
- 深入浅出KNN算法(一) KNN算法原理
一.KNN算法概述 KNN可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一,注意KNN算法是有监督学习中的分类算法,它看起来和另一个机器学习算法Kmeans有点像(Kmeans是无监督学 ...