SAM详解3(SAM与AC自动机的相似性,SAM处理字符串匹配)

SAM

前言

你可能需要先看一看前面两篇文章。

SAM详解1

SAM详解2(初级应用)

然后对于AC自动机这个知识点,博主在几百万年前学过一次,但现在已经忘得差不多了,但还是有一些理解的,所以不确定没学过AC自动机的OIer能否理解本文。

(真会有人和作者一样先学SAM吗?)

本文将结合例题进行具体的讲解。

6. 讲解

还是简单讲解一下AC自动机吧。

可以理解为在 Trie 上做 kmp。而其中的精髓是 fail 指针。

状态 u u u 的 fail 指针指向另一个状态 v v v,其中 v v v u u u 的最长后缀(即在若干个后缀状态中取最长的一个作为 fail 指针),也就是把前面去掉(尽可能少的)一点。

我们注意到 SAM 的 f f f 指针(或者叫 l i n k link link)有同样的性质:儿子是由父亲在前面加字符产生的,那么父亲就可以视作在儿子前面去掉字符。

我们完全可以把 SAM 理解为把某个串的所有子串建立AC自动机,于是在SAM上硬跑匹配。

而SAM处理字符串匹配在 5.2 5.2 5.2 已经讲过了,这里搬张图过来:

在这里插入图片描述

6.1 最长公共子串

SP1811 LCS

题意:输入两个字符串,输出它们的最长公共子串长度,若不存在公共子串则输出 0 0 0
其中字符串长度不超过 2.5 × 1 0 5 2.5\times 10^5 2.5×105

我们把两个串分别称作 s 1 , s 2 s1,s2 s1,s2

对于 s 2 s2 s2 设一个数组为 s l e n [ i ] slen[i] slen[i]

s l e n [ i ] slen[i] slen[i] 表示 s 1 s1 s1 s 1 [ i − s l e n [ i ] + 1 , i ] s1[i−slen[i]+1,i] s1[islen[i]+1,i] s 2 s2 s2 中出现过,即以 i i i 结尾的位置的最长匹配长度。

s l e n slen slen 数组的实际意义是每个前缀匹配出的最长后缀,不难发现 s l e n slen slen 数组的 max ⁡ \max max 就是答案。

代码:

#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N=3e5+1;
ll ans;
int slen[N];
struct SAM{
   
   
	int las,tn;
	int sz[N<<1];
	SAM(){
   
    las
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值