\(\color{#0066ff}{ 题目描述 }\)

题面描述 给定一些字符串,求出它们的最长公共子串 输入格式 输入至多\(10\) 行,每行包含不超过\(100000\) 个的小写字母,表示一个字符串 输出格式 一个数,最长公共子串的长度 若不存在最长公共子串,请输出\(0\) 。

\(\color{#0066ff}{输入格式}\)

几个字符串

\(\color{#0066ff}{输出格式}\)

一个整数,为 所求答案

\(\color{#0066ff}{输入样例}\)

alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa

\(\color{#0066ff}{输出样例}\)

2

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{ 题解 }\)

对第一个字符串建立SAM

每个点维护一个max,min ,分别代表当前字符串匹配的最大len, 全局匹配的最大len

匹配之前,鸡排搞一下,方便递推

每次匹配的时候,max清0, 匹配到哪,就用当前匹配长度len更新当前节点max

匹配完一个后,开始按顺序(已经排好了)扫每个点,更新它的父亲

他父亲的max要跟min(父亲的len, 当前的max)取max

因为叶子维护的是整个前缀,所以不会存在超出的情况,但父亲不一样,要跟自己的len取min,然后跟自己的max取max挺绕的

最后跟所有节点去max就是ans了

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {char ch; int x = 0, f = 1;while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));return x * f;
}
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
struct SAM {
protected:struct node {node *ch[26], *fa;int len, siz, max, min;node(int len = 0, int siz = 0, int max = 0, int min = inf): fa(NULL), len(len), siz(siz), max(max), min(min) {memset(ch, 0, sizeof ch);}};node *root, *tail, *lst;node pool[maxn], *id[maxn];int c[maxn];void extend(int c) {node *o = new(tail++) node(lst->len + 1, 1), *v = lst;for(; v && !v->ch[c]; v = v->fa) v->ch[c] = o;if(!v) o->fa = root;else if(v->len + 1 == v->ch[c]->len) o->fa = v->ch[c];else {node *n = new(tail++) node(v->len + 1), *d = v->ch[c];std::copy(d->ch, d->ch + 26, n->ch);n->fa = d->fa, d->fa = o->fa = n;for(; v && v->ch[c] == d; v = v->fa) v->ch[c] = n;}lst = o;}void clr() {tail = pool;root = lst = new(tail++) node();}
public:SAM() { clr(); }void ins(char *s) { for(char *p = s; *p; p++) extend(*p - 'a'); }void getid() {int maxlen = 0;for(node *o = pool; o != tail; o++) c[o->len]++, maxlen = std::max(maxlen, o->len);for(int i = 1; i <= maxlen; i++) c[i] += c[i - 1];for(node *o = pool; o != tail; o++) id[--c[o->len]] = o;}void match(char *s) {node *o = root;int len = 0;for(char *p = s; *p; p++) {int pos = *p - 'a';if(o->ch[pos]) o = o->ch[pos], len++;else {while(o && !o->ch[pos]) o = o->fa;if(!o) o = root, len = 0;else len = o->len + 1, o = o->ch[pos];}o->max = std::max(o->max, len);}for(int i = tail - pool - 1; i; i--) {node *o = id[i];if(o->fa) o->fa->max = std::max(o->fa->max, std::min(o->max, o->fa->len));o->min = std::min(o->min, o->max);o->max = 0;}}int getans() {int ans = 0;for(int i = tail - pool - 1; i; i--) ans = std::max(ans, id[i]->min);return ans;}
}sam;
char s[maxn];
int main() {scanf("%s", s);sam.ins(s);sam.getid();while(~scanf("%s", s)) sam.match(s);printf("%d\n", sam.getans());return 0;
}

转载于:https://www.cnblogs.com/olinr/p/10252291.html

SP1812 LCS2 - Longest Common Substring II相关推荐

  1. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)【两种做法】

    SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)[两种做法] 手动博客搬家: 本文发表于20181217 23:54:35, 原地址https: ...

  2. Spoj LCS2 - Longest Common Substring II

    题目描述 A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is ...

  3. SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机、状压DP)

    手动博客搬家: 本文发表于20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人生第一道后缀自 ...

  4. SPOJ - LCS2 Longest Common Substring II(后缀自动机)

    题目链接:点击查看 题目大意:给出n个字符串,求出最长公共子串的长度 题目分析:之前做过了求两个字符串最长公共子串的长度,相对来说那个题目还算是比较简单入门的,这个题目就稍微有点加大难度了,其实难度也 ...

  5. SPOJ1812 LCS2 - Longest Common Substring II(SAM)

    题目链接 分析: SAM求多串最长公共子串 详解戳这里 #include<cstdio> #include<cstring> #include<iostream>u ...

  6. 后缀自动机求多个串的最长公共子串+拓补排序讲解+LCS2 - Longest Common Substring II

    网上所有关于后缀自动机拓补排序的文章,都默认读者会拓补排序,简直了. 后缀自动机的拓补排序,就是按照长度进行排序,在进行特定操作的时候,通过较长的后缀来更新较短的后缀.那么也就是通过拓补排序中排名靠后 ...

  7. spoj Longest Common Substring II

    Longest Common Substring II SPOJ - LCS2 求10个串的LCS /*1.用第一个串建立后缀自动机2.len[s] 表示状态s 所能代表的字符串的最大长度mx[s] ...

  8. SPOJ LCS Longest Common Substring

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

  9. JavaScript实现longest Common Substring最长公共子串算法(附完整源码)

    JavaScript实现longest Common Substring最长公共子串算法(附完整源码) longestCommonSubstring.js完整源代码 longestCommonSubs ...

  10. 省选专练之后缀自动机SPOJ1811LCS - Longest Common Substring

    陈老师引入SAM的例题 求两个串的LCS 直接建一个串的SAM,并且把另外一个串放进去跳. 这个方法很经典! 几乎满足了所有两个串的公共串问题的所有解法 有巨子说这个跳是均摊Log的,我也不知道QwQ ...

最新文章

  1. Error: module pages/utils/util is not defined
  2. 438. Find All Anagrams in a String
  3. C#中通过单例模式以及Dictionary实现键值对的映射,通过key获取value
  4. Spring Boot Spring MVC 异常处理的N种方法 1
  5. 关于昌平100度健身俱乐部全民健身情况调查报告
  6. 一个路径下挂载(匹配)多个子组件
  7. 逻辑回归(logistic regression)的本质——极大似然估计
  8. python批量生成图_利用Python批量生成任意尺寸的图片
  9. linux系统运行pbs出现ntf,Linux系统启动故障修复
  10. spring框架 web开发_go语言web开发框架学习:Iris框架讲解(一)
  11. java ssm 项目_ssm开源java博客项目,基于maven搭建
  12. mysql 绕过权限检查_跳过权限检查,强制修改mysql密码
  13. HttpClient_002_中文乱码、HttpClient中文乱码透析、总结
  14. 数据挖掘与数据化运营实战. 3.2 目标客户的预测(响应、分类)模型
  15. 使用WinIO库实现保护模式下的IO和内存读写(_inp,_outp)
  16. 如何使用python游戏开发模块—pygame?
  17. 一个清华学子写的关于directshow的学习心得
  18. MTC160-16-ASEMI可控硅模块MTC160-16
  19. 计算机科学与技术研究生课表,计算机科学与技术专业2018级研究生课程表.doc
  20. uniapp引用iconfont字体图标

热门文章

  1. 默认情况下linux主机在机房托管期间被,托管机房作业未传之秘
  2. 华为服务器修改登录密码,服务器登录修改密码
  3. 用 Truffle 插件自动在Etherscan上验证合约代码
  4. FISCO BCOS 跨链WeCross ppt
  5. bootstrap 4 自动水平居中
  6. 软件工程 结对编程 设计结对 单元测试结对 评审结对 是什么
  7. 微信小程序云开发-时间存储、转换、比较
  8. 最好的git命令行基础使用教程 windows
  9. Java 将鼠标改为图片的两种方法
  10. php 会话 写入浏览器,创建PHP会话变量会挂起我的浏览器