全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

C++怎么实现一个后缀自动机(SAM)_C++处理所有子串问题的强大字符串数据结构

c++kquote>后缀自动机SAM是高效处理字符串子串问题的数据结构,能在O(n)时间内构建,支持查询子串出现次数、最长公共子串和不同子串个数;其核心由状态节点、转移边、后缀链接组成,通过扩展字符并维护len与link实现,关键步骤包括新建状态、沿后缀链接跳转、判断是否分裂状态以保证最小性;C++实现使用vector存储状态,map处理转移,常见应用有DP统计不同子串总数、反向传播计算出现频率、在SAM上匹配求两串最长公共子串等。

后缀自动机(Suffix Automaton, SAM)是一种高效处理字符串子串问题的数据结构。它能在 O(n) 时间内构建,并支持快速查询所有子串的出现次数、最长公共子串、不同子串个数等问题。C++ 实现 SAM 的核心是理解其状态转移机制和后缀链接(suffix link)。

什么是后缀自动机

SAM 是一个最小化确定性有限自动机,能识别字符串的所有后缀对应的子串。每个状态代表一组具有相同“右端行为”的子串集合。关键组成部分包括:

  • 状态节点:包含 len(该状态表示的最长子串长度)、link(后缀链接指向更短的等价类)
  • 转移边 trans[c]:字符 c 的转移函数
  • last:当前添加字符后的最新状态

构建后缀自动机的步骤

每次向字符串末尾添加一个字符时,扩展自动机结构。主要逻辑如下:

  • 新建状态 cur,设置其 len 为 last->len + 1
  • 从 last 开始沿后缀链接向上跳,若没有 c 转移,则指向 cur
  • 遇到已有 c 转移的节点 p,设 q = p->trans[c]
  • 根据 len[q] 是否等于 len[p]+1 分裂状态或直接连接后缀链接

注意:分裂状态是为了保证 SAM 的最小性和正确性。

C++ 实现代码

以下是简洁可运行的 SAM 实现:

```cpp #include using namespace std;

struct State { int len, link; map trans; long long cnt; // 表示到达该状态的路径数(可用于统计子串数量) State() : len(0), link(-1), cnt(0) {} };

vector st; int last = 0;

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;

}

常见应用与操作

SAM 构建完成后可以解决多种问题:

  • 不同子串个数:从初始状态出发,每条路径对应唯一子串。可用 DP 计算:f[u] = 1 + Σ f[v](v 是 u 的转移目标)
  • 每个子串出现次数:对每个状态标记是否为终止状态(出现在原串结尾),然后沿后缀链接反向传播计数
  • 最长公共子串(两个串):在 SAM 上匹配第二个串,维护当前匹配长度和状态,不断通过后缀链接调整

例如统计不同子串总数:

```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++  # include  # 字符串  # char  # int  # void  # 数据结构  # using  # Struct  # Namespace  # len  # map  # 能在  # 时间内  # 是一个  # 是一种  # 已有  # 出现在  # 第二个  # 跳转  # 仅限 


相关文章: Swift中swift中的switch 语句  如何在腾讯云免费申请建站?  非常酷的网站设计制作软件,酷培ai教育官方网站?  网站代码制作软件有哪些,如何生成自己网站的代码?  建站之星安全性能如何?防护体系能否抵御黑客入侵?  北京的网站制作公司有哪些,哪个视频网站最好?  b2c电商网站制作流程,b2c水平综合的电商平台?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  如何用y主机助手快速搭建网站?  建站之星免费模板:自助建站系统与智能响应式一键生成  如何用虚拟主机快速搭建网站?详细步骤解析  建站之星在线客服如何快速接入解答?  家具网站制作软件,家具厂怎么跑业务?  建站之星免费版是否永久可用?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?  ,网页ppt怎么弄成自己的ppt?  如何通过cPanel快速搭建网站?  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  香港服务器网站卡顿?如何解决网络延迟与负载问题?  建站之星3.0如何解决常见操作问题?  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  如何通过网站建站时间优化SEO与用户体验?  已有域名和空间如何搭建网站?  如何批量查询域名的建站时间记录?  长沙企业网站制作哪家好,长沙水业集团官方网站?  北京专业网站制作设计师招聘,北京白云观官方网站?  如何用PHP快速搭建高效网站?分步指南  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  零基础网站服务器架设实战:轻量应用与域名解析配置指南  建站之星下载版如何获取与安装?  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  如何用低价快速搭建高质量网站?  营销式网站制作方案,销售哪个网站招聘效果最好?  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  网站制作难吗安全吗,做一个网站需要多久时间?  如何解决VPS建站LNMP环境配置常见问题?  定制建站流程解析:需求评估与SEO优化功能开发指南  湖州网站制作公司有哪些,浙江中蓝新能源公司官网?  python的本地网站制作,如何创建本地站点?  javascript基本数据类型及类型检测常用方法小结  已有域名如何快速搭建专属网站?  成都网站制作报价公司,成都工业用气开户费用?  如何在IIS中配置站点IP、端口及主机头?  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  如何快速搭建二级域名独立网站?  c++怎么用jemalloc c++替换默认内存分配器【性能】  c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】  如何在橙子建站中快速调整背景颜色?  如何在服务器上三步完成建站并提升流量? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。