【Codevs3160】最长公共子串

当然先虐SAM裸题QwQ

3160 最长公共子串

时间限制: 2 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

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

输入描述 Input Description

读入两个字符串

输出描述 Output Description

输出最长公共子串的长度

样例输入 Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit

yeaphowmuchiloveyoumydearmother

样例输出 Sample Output

27

数据范围及提示 Data Size & Hint

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

对第一个串建好SAM把第二个串放进SAM运行就好了.随时记录一下当前匹配子串的长度最后取max.

在build函数和solve函数里循环终止条件一开始没用l竟然跑了3000msQAQ

用l取代之后只有89ms_(:зゝ∠)_

注意给SAM的变量多开点,因为状态数和转移数并不是只有n个的…有一些多余的.一开始脑残了只开了105RE不止.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
#define MAXINT 0x7fffffff
using namespace std;
int ans;
char ch[MAXN];
struct sam
{
    int last,cnt,p,q,np,nq;
    int a[MAXN][26],len[MAXN],fa[MAXN];
    sam()
    {
        last = ++cnt;
    }
    void insert(int c)
    {
        p = last;np = last = ++cnt;len[np] = len[p] + 1;
        while (!a[p][c] && p)   a[p][c] = np,p = fa[p];
        if (!p) fa[np] = 1;
        else
        {
            q = a[p][c];
            if (len[p] + 1 == len[q])   fa[np] = q;
            else
            {
                nq = ++cnt;len[nq] = len[p] + 1;
                memcpy(a[nq],a[q],sizeof(a[q]));
                fa[nq] = fa[q];
                fa[np] = fa[q] = nq;
                while (a[p][c] == q)    a[p][c] = nq,p = fa[p];
            }
        }
    }
    void build()
    {
        scanf("%s",ch+1);
        int l=strlen(ch+1);
        for (int i = 1;i <= l;i++)  insert(ch[i] - ‘a‘);
    }
    void solve()
    {
        scanf("%s",ch+1);
        int tmp = 0,l=strlen(ch+1);
        for (int i = 1;i <= l;i++)
        {
            int c = ch[i] - ‘a‘;
            if (a[p][c])    p = a[p][c],tmp++;
            else
            {
                while (p && !a[p][c])   p = fa[p];
                if (!p) p = 1,tmp = 0;
                else    tmp = len[p] + 1,p = a[p][c];
            }
            ans = max(ans,tmp);
        }
    }
}sam;
int main()
{
    sam.build();
    sam.solve();
    printf("%d",ans);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 17:10:06

【Codevs3160】最长公共子串的相关文章

[codevs3160]最长公共子串解题报告|后缀自动机

给出两个由小写字母组成的字符串,求它们的最长公共子串的长度. 样例就觉得不能更眼熟啊...好像之前用后缀数组做过一次 然后发现后缀自动机真的好好写啊...(当然当时学后缀数组的时候也这么认为... 这道题直接把第一个串放到后缀自动机里 第二个串在上面做匹配,但是要注意匹配的时候不能乱搞... 刚开始写了一个类似KMP的东西...想想不对啊 毕竟有些节点的深度是不对的 然而后来发现,我们可以用一个变量tem来保存当前的长度值 如果可以继续匹配,这个值就+1 否则就开始用fail指针不停地退,直到退

求最长公共子串

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

最长公共子串

(连续) - 阿里笔试[分析+编码] 题目描述:给定一个query和一个text,均由小写字母组成.要求在text中找出以同样的顺序连续出现在query中的最长连续字母序列的长度.例如,query为“acbac”,text为“acaccbabb”,那么text中的“cba”为最长的连续出现在query中的字母序列,因此,返回结果应该为其长度3.请注意程序效率. [思路]用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0.然后求出对角线最长的1序列,其对应的位置

一天一道算法题(5)---最长公共子串

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子串.例如:str1="1AB2345CD",str2="12345EF",公共子串是"2345" 解析 最长公共子串和最长公共子序列的区别是,子串是连续的,子序列是不连续的. 首先还是要生成动态规划表.生成大小为M*N的矩阵dp.dp[i][j]的含义是,在必须把str1[i]和str2[j]当作公共子串最后一个字符的情况下,公共子串最长能有多长.比如,str1="A12

3160 最长公共子串

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

[URAL-1517][求两个字符串的最长公共子串]

Freedom of Choice URAL - 1517 Background Before Albanian people could bear with the freedom of speech (this story is fully described in the problem "Freedom of speech"), another freedom - the freedom of choice - came down on them. In the near fu

POJ 2774 最长公共子串

对于最长公共子串,n*m的递推显然无法通过本题. 本题是后缀数组的一个基础应用,字符串的子串可以视作后缀的前缀. 我们在两个串间插入一个不在字符集的字符如'#'作为连接,这样做的目的是为了防止两个后缀的最长公共前缀跨过第一个字符串的末尾. 扫描Height数组,如果排名为i的字符串与排名为i-1的字符串来源于原来的2个串,则更新答案最大值. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm>

【wikioi】3160 最长公共子串(后缀自动机)

http://codevs.cn/problem/3160/ sam的裸题...(之前写了spoj上另一题sam的题目,但是spoj被卡评测现在还没评测完QAQ打算写那题题解时再来详细介绍sam的....那就再等等吧. 求两个串的lcs话,就是先建立a串的sam,然后用b的字串去匹配a中. 因为sam中每个状态的len对应最长子串,因此自动机不断trans匹配时,如果没找到下一个点,那么在parent树的祖先中找是否还有子串可以更新(因为祖先的max比这个节点小,且都包含当前状态的right,所

字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍. 这题的思路是这样的: 1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界:不存在就缩小上界): 2)主要是对答案的判断(judge函数