3160 最长公共子串

题目描述 Description

给出两个由小写字母组成的字符串,求它们的最长公共子串的长度。

输入描述 Input Description

读入两个字符串

输出描述 Output Description

输出最长公共子串的长度

样例输入(Sample Input)

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit

yeaphowmuchiloveyoumydearmother

样例输出(Sample Output)

27

数据范围及提示

单个字符串的长度不超过100000

将两个串链接成一个串,之后直接求hight数组即可,同时要求:

  1. 两个后缀只来自各自的字符串

    这一点只要在中间加个特殊字符即可,因为只要使得两个后缀的起始点来自于不同串,特殊字符会使得他们在求lcp时断开
/*
作者:Acforgood
题目:p3160 最长公共子串
*/ #include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 300
#define mod 1000000007
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=200005;
int n;
char ch[N];
int a[N],h[N];
int v[N];
int sa[2][N],rk[2][N];
int p,q,k;
void calsa(int sa[N],int rk[N],int SA[N],int RK[N])
{
for(int i=1; i<=n; i++)v[rk[sa[i]]]=i;
for(int i=n; i; i--)
if(sa[i]>k)
SA[v[rk[sa[i]-k]]--]=sa[i]-k;
for(int i=n-k+1; i<=n; i++)SA[v[rk[i]]--]=i;
for(int i=1; i<=n; i++)
RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
}
void work()
{
p=0,q=1;
for(int i=1; i<=n; i++)v[a[i]]++;
for(int i=1; i<=30; i++)v[i]+=v[i-1];
for(int i=1; i<=n; i++)
sa[p][v[a[i]]--]=i;
for(int i=1; i<=n; i++)
rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
for(k=1; k<n; k<<=1)
{
calsa(sa[p],rk[p],sa[q],rk[q]);
swap(p,q);
}
}
void geth()
{
k=0;
for(int i=1; i<=n; i++)
if(rk[p][i]==1)h[rk[p][i]]=0;
else
{
int j=sa[p][rk[p][i]-1];
while(a[i+k]==a[j+k])k++;
h[rk[p][i]]=k;
if(k>0)k--;
}
}
int main()
{
while(~scanf("%s",ch+1))
{
n=strlen(ch+1);
int len=n+1;
ch[n+1]='a'-1;
scanf("%s",ch+n+2);
n=strlen(ch+1);
for(int i=1; i<=n; i++)a[i]=ch[i]-'a'+1;
work();
geth();
int ans=0;
for(int i=1; i<=n; i++)
{
if((sa[p][i]>len&&sa[p][i-1]<len)||(sa[p][i]<len&&sa[p][i-1]>len)) ans=max(ans,h[i]);
}
printf("%d\n",ans);
}
return 0;
}

CODE【VS】 3160 最长公共子串 (后缀数组)的更多相关文章

  1. Codevs 3160 最长公共子串(后缀数组)

    3160 最长公共子串 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给出两个由小写字母组成的字符串,求它们的最长公共子串的长 ...

  2. poj 2774 最长公共子串 后缀数组

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 25752   Accepted: 10 ...

  3. POJ 2774 Long Long Message [ 最长公共子串 后缀数组]

    题目:http://poj.org/problem?id=2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total ...

  4. 【codevs3160】最长公共子串 后缀数组

    题目描述 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入 读入两个字符串 输出 输出最长公共子串的长度 样例输入 yeshowmuchiloveyoumydearmotherrea ...

  5. codevs 3160 最长公共子串 后缀自动机

    http://codevs.cn/problem/3160/ 后缀自动机板子题,匹配的时候要注意如果到一个点失配向前匹配到一个点时,此时的tmp(当前匹配值)为t[j].len+1而不是t[t[j]. ...

  6. CODE【VS】3160 最长公共子串 (后缀自动机)

    3160 最长公共子串 题目描述 Description 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入描述 Input Description 读入两个字符串 输出描述 Outp ...

  7. codevs 3160 最长公共子串

    3160 最长公共子串 http://codevs.cn/problem/3160/  时间限制: 2 s  空间限制: 128000 KB   题目描述 Description 给出两个由小写字母组 ...

  8. codevs 3160 最长公共子串(SAM)

    3160 最长公共子串   题目描述 Description 给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 输入描述 Input Description 读入两个字符串 输出描述 Ou ...

  9. poj 1743 Musical Theme(最长重复子串 后缀数组)

    poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...

随机推荐

  1. Unix\Linux | 总结笔记 | 查看文件的方式

    0 目录 vi cat head tail more less 1.vi vi编辑器的内置命令 有些内置命令使用键盘组合键即可完成,有些内置命令则需要以冒号“:”开头输入.常用内置命令如下: Ctrl ...

  2. 拓扑排序/DFS HDOJ 4324 Triangle LOVE

    题目传送门 题意:判三角恋(三元环).如果A喜欢B,那么B一定不喜欢A,任意两人一定有关系连接 分析:正解应该是拓扑排序判环,如果有环,一定是三元环,证明. DFS:从任意一点开始搜索,搜索过的点标记 ...

  3. 数学 Codeforces Round #282 (Div. 2) B. Modular Equations

    题目传送门 题意:a % x == b,求符合条件的x有几个 数学:等式转换为:a == nx + b,那么设k = nx = a - b,易得k的约数(>b)的都符合条件,比如a=25 b=1 ...

  4. Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/NamespaceContext

    使用dom4j的xpath查询节点,报如下错误: Exception in thread "main" java.lang.NoClassDefFoundError: org/ja ...

  5. 08 H5新增input元素

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. Java几种常见的排序方法

    日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序,甚至还有基数排序.鸡尾酒排序.桶排序.鸽巢排序.归并排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一 ...

  7. CentOS7搭建LAMP

    阿里云CentOS7.3搭建 Apache+MySQL+PHP环境 参考https://www.cnblogs.com/apro-abra/p/4862285.html   一.安装Apache 1. ...

  8. GCC的函数声明问题

    Thinking in C++ 第四章 GCC 不需要再MAIN函数前声明 编译也能通过. G++不行.

  9. 51全志R58平台Android4.4下Camera的HAL层修改

    51全志R58平台Android4.4下Camera的HAL层修改 2018/11/7 15:20 版本:V1.0 开发板:SC5806 1.系统编译: (略) 2.全志R58平台Android4.4 ...

  10. R in action读书笔记(6)-第七章:基本统计分析(中)

    7.2 频数表和列联表 > library(vcd) > head(Arthritis) ID Treatment Sex Age Improved 1 57 Treated Male 2 ...