SPOJ 1811 SAM 初探

思路:

一个串建SAM

另一个串在SAM上跑

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=500050;
int n;char a[N],b[N];
struct SAM{
    int ch[N][26],dis[N],fa[N],root,tot,last;
    void init(){root=tot=last=1;}
    int newnode(int v){return dis[++tot]=v,tot;}
    void add(int x){
        int p=last,np=newnode(dis[p]+1);last=np;
        for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np;
        if(!p)fa[np]=root;
        else{
            int q=ch[p][x];
            if(dis[q]==dis[p]+1)fa[np]=q;
            else{
                int nq=newnode(dis[p]+1);
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q],fa[np]=fa[q]=nq;
                for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
            }
        }
    }
}T;
int main(){
    T.init();
    scanf("%s%s",a+1,b+1);
    int n=strlen(a+1),m=strlen(b+1),ans=0,len=0;
    for(int i=1;i<=n;i++)T.add(a[i]-‘a‘);
    int p=T.root;
    for(int i=1;i<=m;i++){
        int x=b[i]-‘a‘;
        if(T.ch[p][x])len++,p=T.ch[p][x];
        else{
            for(;p&&!T.ch[p][x];p=T.fa[p]);
            if(!p)p=T.root,len=0;
            else len=T.dis[p]+1,p=T.ch[p][x];
        }ans=max(ans,len);
    }printf("%d\n",ans);
}
时间: 2025-01-07 20:54:19

SPOJ 1811 SAM 初探的相关文章

spoj 1811 LCS - Longest Common Substring (后缀自动机)

spoj 1811 LCS - Longest Common Substring 题意: 给出两个串S, T, 求最长公共子串. 限制: |S|, |T| <= 1e5 思路: dp O(n^2) 铁定超时 后缀数组 O(nlog(n)) 在spoj上没试过,感觉也会被卡掉 后缀自动机 O(n) 我们考虑用SAM读入字符串B; 令当前状态为s,同时最大匹配长度为len; 我们读入字符x.如果s有标号为x的边,那么s=trans(s,x),len = len+1; 否则我们找到s的第一个祖先a,它

spoj 1811

1811. Longest Common Substring Problem code: LCS 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 occur

【刷题】SPOJ 1811 LCS - Longest Common Substring

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 i

SPOJ 1811 Longest Common Substring(求两个串的最长公共子串)

http://www.spoj.com/problems/LCS/ 题目:求两个串的最长公共子串 分析: 以A建立SAM 让B在SAM上匹配可以类比于kmp思想,我们知道在Parent树上,fa是当前节点的子集,也就是说满足最大前缀,利用这个就可以做题了 #include <bits/stdc++.h> #define LL long long #define P pair<int, int> #define lowbit(x) (x & -x) #define mem(a

SAM初探

SAM,即Suffix Automaton,后缀自动机. 关于字符串有很多玩法,有很多算法都是围绕字符串展开的.为什么?我的理解是:相较于数字组成的序列,字母组成的序列中每个单位上元素的个数是有限的.对于有限的东西,相较于无限的东西就会具有一些奇妙的性质.最简单的,就是序列扩展成的树每个节点的儿子数是有限的.所以根据这个,从字符串Hash,到KMP,再到Suffix Array,Suffix Automaton,纷纷诞生. 后缀数组在处理字符串上相当于一把好钢,他能应付在字符串的大多数问题.那么

SPOJ 1811 Longest Common Substring

Description 给出两个字符串,求最长公共子串. Sol SAM. 这题随便做啊...后缀数组/Hash+二分都可以. SAM就是模板啊...直接在SAM上跑就行,没有了 \(go[w]\) 就往 \(par\) 跳. 每走一步统计一下答案. Code #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N = 250005; struct St

●SPOJ 1811 Longest Common Substring

题链: http://poj.org/problem?id=2774 题解: 求两个字符串(S,T)的最长公共子串.对 S串建后缀自动机.接下来就用这个自动机去求出能和 S串匹配的 T的每一个前缀的最长的后缀.最终答案就是对每个 T的前缀得到的答案取最大值就好了. 代码: #include<cstdio> #include<cstring> #include<iostream> #define MAXN 250050 #define filein(x) freopen(

spoj 1812 LCS2 - Longest Common Substring II (后缀自动机)

spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 <= n <= 10 |A[i]| <= 1e5 思路: 和spoj 1811 LCS差不多的做法 把其中一个A建后缀自动机 考虑一个状态s, 如果A之外的其他串对它的匹配长度分别是a[1], a[2], ..., a[n - 1], 那么min(a[1], a[2], ..., a[n - 1]

后缀自动机(SAM)学习指南

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.