SP1811

题目描述

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is simple, for two given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

输入格式

The input contains exactly two lines, each line consists of no more than 250000 lowercase letters, representing a string.

输出格式

The length of the longest common substring. If such string doesn’t exist, print “0” instead.

题意翻译

输入2 个长度不大于250000的字符串,输出这2 个字符串的最长公共子串。如果没有公共子串则输出0 。

Translated by @xyz32768

输入输出样例

输入

alsdfkjfjkdsal

fdjskalajfkdsla

输出

3

有两个字符串AAA和BBB,我们要求它们的最长公共连续子串。

首先,我们对AAA建立一个SAMSAMSAM。

定义:LenLenLen为当前BBB的前iii个字符组成的子串与AAA的最长公共子序列,StateStateState为当前状态,初始化为0(初始状态)。next(State,ch)next(State,ch)next(State,ch)为在StateStateState状态节点处往chchch道路走的下一状态。

匹配

然后我们从B[i=0]B[i=0]B[i=0]开始,在AAA的SAMSAMSAM上走,一个一个匹配,若:

  1. 当前状态朝着B[i]B[i]B[i]往下走有路,说明可以继续往下匹配,就接着走,即State=next(State,B[i]),++LenState=next(State,B[i]),++LenState=next(State,B[i]),++Len。
  2. 如果没有路了,就跳到当前状态在后缀连接树上的父节点,如果父节点还是没有B[i]B[i]B[i]的路,就一直往上跳(即State=link(State)State=link(State)State=link(State)),直到遇到能往下走的边。此时就令Len=len(当前状态)+1Len=len(当前状态)+1Len=len(当前状态)+1,State=next(State,B[i])State=next(State,B[i])State=next(State,B[i])。
  3. 如果跳到头了都没有能走的路的话,就说明要从B[i]开始重新匹配,令Len=0,State=0Len=0,State=0Len=0,State=0。

原理:如果B[i]B[i]B[i]在当前位置下失配(无路可走),那么说明当前状态下的所有子串都失配了,但是它的后缀连接树上的父节点不一定失配,就继续往上找,即相当于当前已经匹配的AAA的子串的左边界往右移,然后继续找路。如果一直没路,就一直往上找,直到达到 初始状态 ,如果此时仍没有路的话,说名在当前LenLenLen长度下已经是B[上一次从初始状态开始匹配的i]B[上一次从初始状态开始匹配的i]B[上一次从初始状态开始匹配的i]开始的最长公共子串了,无法在加长了。那就让Ans=max(Ans,Len)Ans=max(Ans,Len)Ans=max(Ans,Len),让后以B[i]B[i]B[i]为新的开头从初始状态重新开始匹配。即整个过程就是再找BBB的所有前缀的后缀最长能和AAA匹配多少。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
const int MAXN = 250005;
int n;
char
A[MAXN],
B[MAXN];
struct SAM {
int size, last;
struct Node {
int len = 0, link = 0;
int next[26];
void clear() {
len = link = 0;
memset(next, 0, sizeof(next));
}
} node[MAXN * 2];
void init() {
for (int i = 0; i < size; i++) {
node[i].clear();
}
node[0].link = -1;
size = 1;
last = 0;
}
void insert(char x) {
int ch = x - 'a';
int cur = size++;
node[cur].len = node[last].len + 1;
int p = last;
while (p != -1 && !node[p].next[ch]) {
node[p].next[ch] = cur;
p = node[p].link;
}
if (p == -1) {
node[cur].link = 0;
}
else {
int q = node[p].next[ch];
if (node[p].len + 1 == node[q].len) {
node[cur].link = q;
}
else {
int clone = size++;
node[clone] = node[q];
node[clone].len = node[p].len + 1;
while (p != -1 && node[p].next[ch] == q) {
node[p].next[ch] = clone;
p = node[p].link;
}
node[q].link = node[cur].link = clone;
}
}
last = cur;
}
}sam;
int getNextState(const int& CurState,int Loc) {
return sam.node[CurState].next[Loc - 'a'];
}
int Compute(int n) {
int
&& Ans = 0,
&& CurState = 0,
&& Len = 0;
for (int i = 0; i < n; ++i) {
//如果有路可走,就走噻
if (getNextState(CurState, B[i])) {
CurState = getNextState(CurState, B[i]);
++Len;
}
//否则
else {
//跳link
for (CurState = sam.node[CurState].link;; CurState = sam.node[CurState].link) {
//如果跳到了
if (CurState > 0 && getNextState(CurState, B[i])) {
Len = sam.node[CurState].len + 1;
CurState = getNextState(CurState, B[i]);
break;
}
//如果跳到初始状态。
else if (CurState <= 0) {
Len = 0;
CurState = 0;
break;
}
}
}
Ans = max(Ans, Len);
}
return Ans;
}
int main() {
scanf("%s%s", &A, &B);
int Len_A = strlen(A);
sam.init();
for (int i = 0; i < Len_A; ++i) {
sam.insert(A[i]);
}
printf("%d", Compute(strlen(B)));
return 0;
}

Longest Common Substring(最长公共子串)的更多相关文章

  1. lintcode 77.Longest Common Subsequence(最长公共子序列)、79. Longest Common Substring(最长公共子串)

    Longest Common Subsequence最长公共子序列: 每个dp位置表示的是第i.j个字母的最长公共子序列 class Solution { public: int findLength ...

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

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

  3. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  4. poj 1458 Common Subsequence_最长公共子串

    题意:略 求最长公共子串 #include<iostream> #include<cstdio> #include<string> using namespace ...

  5. LCS(Longest Common Subsequence)最长公共子序列

    最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题.这与查找最长公共子串的问题不同的地方是:子序列不需要在原序列中占用连续的位置 .最长公共子序列问题是 ...

  6. 【LeetCode】14. Longest Common Prefix 最长前缀子串

    题目: Write a function to find the longest common prefix string amongst an array of strings. 思路:求最长前缀子 ...

  7. [LeetCode]14. Longest Common Prefix最长公共前缀

    Write a function to find the longest common prefix string amongst an array of strings. If there is n ...

  8. # Leetcode 14:Longest Common Prefix 最长公共前缀

    公众号:爱写bug Write a function to find the longest common prefix string amongst an array of strings. If ...

  9. 【LeetCode】14. Longest Common Prefix 最长公共前缀

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:prefix, 公共前缀,题解,leetcode, 力扣 ...

  10. Leetcode No.14 Longest Common Prefix最长公共前缀(c++实现)

    1. 题目 1.1 英文题目 Write a function to find the longest common prefix string amongst an array of strings ...

随机推荐

  1. 【NPDP专项练习】第七章 产品生命周期管理

    第七章 产品生命周期管理 1.以下哪一项是产品生命周期缩短的原因之一? A 技术停滞不前 B 减少竞争 C 顾客要求更高 D 沟通障碍正在增加 答案:C 解析 A技术持续进步:B竞争加剧:D沟通增加 ...

  2. vue高级进阶( 三 ) 组件高级用法及最佳实践

      vue高级进阶( 三 ) 组件高级用法及最佳实践 世界上有太多孤独的人害怕先踏出第一步. ---绿皮书 书接上回,上篇介绍了vue组件通信比较有代表性的几种方法,本篇主要讲述一下组件的高级用法和最 ...

  3. PCA降维练习

    [题目] 1.现有我国大陆30个省.直辖市.自治区的经济发展状况数据集如表所示,包括8项经济指标:国民生产总值(A1):居民消费水平(A2):固定资产投资(A3):职工平均工资(A4):货物周转量(A ...

  4. pytorch的cuda版本安装

    机器上加了RTX3060的卡,cuda装的11.1的版本,cudnn还不是特别清楚装的哪个版本?vs是2017这个版本的.下面来装pytorch.主要参考这个网站的内容"https://bl ...

  5. iOS证书签名

    苹果官方有一对密钥,即私钥和公钥,私钥在苹果后台,公钥在iOS系统中(如iPhone手机在出厂后,其中就保存有苹果官方的公钥):在Mac系统打包app时也会生成一对密钥(私钥.公钥),并保存在钥匙串中 ...

  6. ctfshow CRYPTO RSA系列

    ctfshow CRYPTO RSA系列 目录 ctfshow CRYPTO RSA系列 babyRSA 分析 解题 esayrsa1 分析 解题 esayrsa2 分析 解题 esayrsa3 分析 ...

  7. 虚拟机重置root用户密码

    虚拟机root用户重置密码 在打开虚拟机 在出现下图界面的时候按 e 进入管理界面 e要快速按 不然就会直接进入虚拟机 然后找到 UTF-8 在后面添加 rd.break 输入完后按 Ctrl+x 跳 ...

  8. 利用Comparator对枚举类型进行排序的实现

    1. 利用BeanComparator对List<Object>根据属性进行排序 String daXiaoOrder[] = {"很小","小", ...

  9. django自定义管理类的save model和delete model记一次进一步了解

    业务背景: 最近在写一个个人博客网站,文章分类是一个自关联的两层分类.希望在点开分类时,显示一级分类.一级分类下的所有二级分类以及每个二级分类有多少个文章.最简单办法就是关联查询,查询出所有二级分类, ...

  10. Python面向对象编程——__init()__方法

    隐式基类object 每个python类都隐式继承object 全文代码实例实现:枚举扑克牌的花色和牌面值 一._init()__方法:对象初始化 显示而非隐式:__init()__应显示展示初始化变 ...