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. Django新版本报错问题解决

    在创建app的时候会报如下错误: python3 manage.py startapp test django.core.exceptions.ImproperlyConfigured: SQLite ...

  2. debug 获取mybatis dao 连接的数据库

    MapperProxy.invoke MapperMethod.execute 查看sqlSession .

  3. as8051入门

    汇编例子 MAIN: MOV R0, #16 MOV R1, #16 LOOP: MOV A, R1 MOV @R0,A MOV A,0x0 MOV A, @R0 MOV SBUF, A INC R0 ...

  4. Centos 7.5 MySql的安装和配置

    一.安装 三个步骤: wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpmyum -y ins ...

  5. 2022.11.09 NOIP2022 模拟赛六

    科学 Source:CF461C Appleman and a Sheet of Paper,*2200. 注意到对于 \(p\le \lfloor \frac {now}{2}\rfloor\),直 ...

  6. 项目中pom.xml的某些坐标无法加载

    项目中pom.xml的某些坐标无法加载 maven官方查找对应的坐标文件下载 https://mvnrepository.com/artifact/com.fasterxml.jackson.core ...

  7. Java流程控制之Scanner的进阶使用

    Scanner的进阶使用 import java.util.Scanner; public class Demo04 { public static void main(String[] args) ...

  8. WDA学习(23):UI Element:Radio Button Group & CheckBox Group使用

    1.16 UI Element:Radio Button & CheckBox使用 本实例测试Radio Button Group,CheckBox Group等的使用. 注:Dropdown ...

  9. Kubernetes--案例:使用Ingress发布tomcat

    假设有这样一套环境: Kubernetes集群上的tomcat-deploy控制器生成了两个运行于Pod资源中的tomcat实例,tomcat-svc是将它们统一暴露于集群中的访问入口.现在需要通过I ...

  10. flume往kafka中导入数据

    1.编辑flume的配置文件 a1.sources = r1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = ...