
后缀自动机(Suffix Automaton, SAM)是一种高效处理字符串子串问题的数据结构。它能在 O(n) 时间内构建,并支持快速查询所有子串的出现次数、最长公共子串、不同子串个数等问题。C++ 实现 SAM 的核心是理解其状态转移机制和后缀链接(suffix link)。
SAM 是一个最小化确定性有限自动机,能识别字符串的所有后缀对应的子串。每个状态代表一组具有相同“右端行为”的子串集合。关键组成部分包括:
每次向字符串末尾添加一个字符时,扩展自动机结构。主要逻辑如下:
注意:分裂状态是为了保证 SAM 的最小性和正确性。
立即学习“C++免费学习笔记(深入)”;
以下是简洁可运行的 SAM 实现:
Mistral AI
Mistral AI被称为“欧洲版的OpenAI”,也是目前欧洲最强的 LLM 大模型平台
182
查看详情
```cpp
#include struct State {
int len, link;
map
vector
void sam_init() { st.clear(); st.push_back(State()); last = 0; }
void sam_extend(char c) { int cur = st.size(); st.push_back(State()); st[cur].len = st[last].len + 1; int p = last;
while (p != -1 && !st[p].trans.count(c)) {
st[p].trans[c] = cur;
p = st[p].link;
}
if (p == -1) {
st[cur].link = 0;
} else {
int q = st[p].trans[c];
if (st[p].len + 1 == st[q].len) {
st[cur].link = q;
} else {
int clone = st.size();
st.push_back(st[q]); // 复制 q 状态
st[clone].len = st[p].len + 1;
while (p != -1 && st[p].trans[c] == q) {
st[p].trans[c] = clone;
p = st[p].link;
}
st
[q].link = clone;
st[cur].link = clone;
}
}
last = cur;}
<H3>常见应用与操作</H3>
<p>SAM 构建完成后可以解决多种问题:</p>
<ul>
<li><strong>不同子串个数</strong>:从初始状态出发,每条路径对应唯一子串。可用 DP 计算:f[u] = 1 + Σ f[v](v 是 u 的转移目标)</li>
<li><strong>每个子串出现次数</strong>:对每个状态标记是否为终止状态(出现在原串结尾),然后沿后缀链接反向传播计数</li>
<li><strong>最长公共子串(两个串)</strong>:在 SAM 上匹配第二个串,维护当前匹配长度和状态,不断通过后缀链接调整</li>
</ul>
<p>例如统计不同子串总数:</p>
```cpp
long long count_distinct_substrings() {
long long total = 0;
for (int i = 1; i < st.size(); i++) {
total += st[i].len - st[st[i].link].len;
}
return total;
}基本上就这些。掌握 SAM 关键在于理解状态含义和分裂条件。实现时注意 map 可换成数组(仅限小字符集),提升性能。
以上就是C++怎么实现一个后缀自动机(SAM)_C++处理所有子串问题的强大字符串数据结构的详细内容,更多请关注其它相关文章!
相关文章:
将HTML Canvas内容转换为可上传的图像文件(File对象)
cad如何更改注释性对象的比例_cad注释性比例调整方法
css子元素高度不一致导致布局错位怎么办_使用align-items:stretch解决高度差异
一加手机拍照效果不好怎么办 一加哈苏影像调校与专业模式使用教程【高手篇】
age动漫网站入口 age动漫官网直接访问入口
Typer应用中灵活处理命令行参数的令牌化与解析
浏览器打开即用 美图秀秀网页版入口
CSS自定义字体样式被系统字体替换怎么办_font-face方式指定font-display控制渲染策略
AWS EC2实例间SQL Server连接超时:安全组配置与故障排除指南
微信群消息显示延迟如何解决 微信群消息刷新优化方法
汽水音乐在线版入口_汽水音乐网页播放手册
Python getattr() 异常处理深度解析:避免程序意外退出
整合Supabase认证与Django模型:跨模式迁移的解决方案
J*a TimerTask中HashMap意外清空的深层原因与解决方案
飞书妙记怎样用语音转文字速记_飞书妙记用语音转文字速记【速记方法】
sublime怎么设置启动时打开的窗口_sublime会话管理与热退出
C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果
Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法
1688商家版怎样分析买家画像精准供货_1688商家版分析买家画像精准供货【供货策略】
J*aScript Promise链中如何正确终止后续.then执行并处理错误
在WordPress中通过REST API获取BasicAuth保护的远程文章
使用PHP从URL路径中提取倒数第二个片段
Django通过AJAX异步上传图片并保存至模型的完整指南
谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法
Golang如何使用buffered channel提高性能_Golang buffered channel优化技巧
Python:递归比较文件夹内容并找出特定类型文件的差异
深入理解J*a编译器的兼容性选项:从-source到--release
126邮箱账号注册 电脑版登录入口
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
Tabulator表格中精确实现日期时间排序的指南
将JSON对象数组转置为键值对列表的实用指南
TikTok网页版直接登录 TikTok网页端官方平台入口
Yii2模块参数配置指南:正确声明与访问模块级配置
12306几点到几点不能订票? | 官方最新系统维护时间全解析
AO3镜像入口大全 AO3网页版内容访问全集
iwriter统一登录平台 iwrite账号密码登录页面
Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧
抖音商城签到领现金是真的吗_抖音商城签到奖励与提现说明
使用Python高效删除Word宏并转换DOCM为DOCX格式
必由学官方网站入口 必由学学生教师共用登录通道
如何使 Jest 模拟函数默认抛出错误以提高测试效率
SteamMachine定价或为699美元 大家想入手吗?
微博网页版首页入口 微博电脑端官网登录链接
如何优雅地解决Livewire文件上传难题?SpatieLivewireFilepond让一切变得简单
《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!
J*aScript教程:根据元素文本内容动态设置背景色
支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡
Python中高效且防溢出的双曲正弦计算:基于对数空间的优化策略
解决 Vaadin 8 中大文件音频播放与定位时出现的 IOException
腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录