题目链接:https://cn.vjudge.net/contest/283743#problem/J

题目大意:给你两个字符串,问你两个字符串的最长的公共子串。

具体思路:把两个字符串合在一起,然后求后缀数组,按照排名之后的字符串,如果两个相邻的字符串的sa[i]和sa[i-1]分别属于两个字符串,那么这个就是题目允许的值之一,然后再从这些值里面找一个最大的输出就可以了。

AC代码:

 #include<iostream>
#include<stack>
#include<cstring>
#include<iomanip>
#include<stdio.h>
#include<algorithm>
#include<cmath>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 5e5+;
int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn];
int Rank[maxn];
char ch[maxn];
char str1[maxn];
int sto[maxn];
ll n;
//sa[i]代表第i小的后缀位置,Rank[i]代表第i位置的后缀,排名第几小
// height[i]代表排名第i个字符串和第i-1个字符串的相同前缀有多少个
void cal()
{
for(int i = ; i < ; i++)
cntA[i] = ;
for(int i = ; i <= n; i++)
{
cntA[ch[i-]]++;
}
for(int i = ; i < ; i++)
cntA[i] += cntA[i-];
for(int i = n; i; i--)
sa[cntA[ch[i-]]--] = i;
Rank[sa[]] = ;
for(int i = ; i <= n; i++)
{
Rank[sa[i]] = Rank[sa[i-]];
if(ch[sa[i]-] != ch[sa[i-]-])
Rank[sa[i]]++;
}
for(int l = ; Rank[sa[n]] < n; l <<= )
{
memset(cntA, , sizeof(cntA));
memset(cntB, , sizeof(cntB));
for(int i = ; i <= n; i++)
{
cntA[A[i] = Rank[i]]++;
cntB[B[i] = (i+l <= n)?Rank[i+l]:]++;
}
for(int i = ; i <= n; i++)
cntB[i] += cntB[i-];
for(int i = n; i; i--)
tsa[cntB[B[i]]--] = i;
for(int i = ; i <= n; i++)
cntA[i] += cntA[i-];
for(int i = n; i; i--)
sa[cntA[A[tsa[i]]]--] = tsa[i];
Rank[sa[]]=;
for(int i = ; i <= n; i++)
{
Rank[sa[i]] = Rank[sa[i-]];
if(A[sa[i]] != A[sa[i-]] || B[sa[i]] != B[sa[i-]])
Rank[sa[i]]++;
}
}
for(int i = , j = ; i <= n; i++)
{
if(j)
j--;
while(ch[i+j-] == ch[sa[Rank[i]-] + j - ])
j++;
height[Rank[i]] = j;
}
}
int main()
{
scanf("%s",str1);
int len1=strlen(str1);
for(int i=; i<len1; i++)
{
ch[i]=str1[i];
}
scanf("%s",str1);
int len2=strlen(str1);
for(int i=len1; i<len1+len2; i++)
{
ch[i]=str1[i-len1];
}
n=len1+len2;
cal();
int maxx=;
for(int i=; i<=len1+len2; i++)
{
if(height[i]>maxx)
{
if(sa[i]>=&&sa[i]<=len1&&sa[i-]>=(+len1)&&sa[i-]<=len1+len2)
maxx=height[i];
if(sa[i-]>=&&sa[i-]<=len1&&sa[i]>=(+len1)&&sa[i]<=len1+len2)
maxx=height[i];
}
}
printf("%d\n",maxx);
return ;
}

J - Long Long Message (最长公共子串)的更多相关文章

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

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

  2. 【POJ 2774】Long Long Message 最长公共子串

    还是模板啊,手残&&打成||查错查了1h+TAT #include<cstdio> #include<cstring> #include<algorith ...

  3. 华为OJ之最长公共子串

    题目描述: 对于两个给定的字符串,给出他们的最长公共子串. 题目分析: 1,最长公共子串(LCS)实际上是最长公共子序列的一种特殊情况,相当于是求连续的最长子序列.我们今天先解决这个特殊情况,后续博文 ...

  4. 动态规划经典——最长公共子序列问题 (LCS)和最长公共子串问题

    一.最长公共子序列问题(LCS问题) 给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子序列,并返回其长度.例如: A = "HelloWorld"    B = & ...

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

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

  6. [DP]最长公共子串

    题目 给定两个字符串str1和str2, 长度分别稳M和N,返回两个字符串的最长公共子串 解法一 这是一道经典的动态规划题,可以用M*N的二维dp数组求解.dp[i][j]代表以str1[i]和str ...

  7. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

  8. POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串

    题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072 ...

  9. POJ-2774-Long Long Message(后缀数组-最长公共子串)

    题意: 给定两个字符串 A 和 B,求最长公共子串. 分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长公共子串等价于求 A 的后缀和 B 的后缀的最长公共前缀的最大 ...

  10. poj 2774 Long Long Message,后缀数组,求最长公共子串 hdu1403

    题意:给出两个字符串,求最长公共子串的长度. 题解:首先将两个字符串连在一起,并在中间加一个特殊字符(字串中不存在的)切割,然后两个串的最长公共字串就变成了全部后缀的最长公共前缀.这时就要用到heig ...

随机推荐

  1. P2209 [USACO13OPEN]燃油经济性Fuel Economy

    题面 sol:(思想):开一个大根堆和一个小根堆,每次计算到下了一个加油站用掉的油时尽量用小根堆中的元素,且同时删去大根堆中的相应位置的元素,当前加油站如果足够便宜,就可以把大根堆中的元素替换掉: ( ...

  2. 聊聊我怎么系统学习Linux技能并快速提高的

    随着电子信息科技时代的发展,学会使用计算机在我们的生活中成为了必不可少的一项技能.而作为计算机中的三大操作系统之一的Linux更是饱受计算机爱好者们的喜爱.今天我们就来和大家一起聊一聊Linux操作系 ...

  3. BZOJ4946 NOI2017蔬菜(贪心+堆)

    容易想到一个费用流做法:将每种蔬菜拆成p种,对应p个过期时间,每一种向可以卖的时间连边,第一次卖的奖励算在最晚过期的一种里.对于天数动态加点.不过这样边数太多了,因为第i天能卖的第i-1天一定能卖,可 ...

  4. 【luogu4320】道路相遇 (圆方树 + LCA)

    Description ​ 给你一张\(~n~\)个点\(~m~\)条边的无向图,保证无重边无自环, 共\(~q~\)组询问求\(~x~\)到\(~y~\)的路径上必经的点数. Solution ​ ...

  5. [luogu4264][USACO18FEB]Teleportation

    题解 先吐槽一波题目:便便传送门,出题人还真的有一点厉害的滑稽. 废话不多说. 首先问题的本质就是求如果当这个传送门的端点位于\(y\)的时候,最小的求出总代价,我们设为函数\(f(y)\). 因为这 ...

  6. poco

    源码安装: 1, ./configure --omit=Data/MySQL,Data/ODBC,Zip,Crypto,NetSSL_OpenSSL     --no-samples  --no-te ...

  7. JS循环语句!

    <1> for(1.初始值(初始值只有一次):2.判断条件:4.状态改变){ 3.执行语句: //如果判断条件为true,则进入死循环:不设执行语句浏览器会未响应: } <2> ...

  8. A1032. Sharing

    To store English words, one method is to use linked lists and store a word letter by letter. To save ...

  9. A1051. Pop Sequence

    Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and p ...

  10. sscanf,sprintf 通过字符串与其它类型进行方便快捷的输入和输出

    http://c.biancheng.net/cpp/html/296.html 头文件:#include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据,其原型 ...