自动机

news/2025/10/24 13:34:36/文章来源:https://www.cnblogs.com/xihegudi/p/19163047

AC 自动机

定义 \(|s_i|\) 是模板串的长度,\(|S|\) 是文本串的长度,\(|\Sigma|\) 是字符集的大小(常数,一般为 \(26\)),时间复杂度为 \(\mathcal O(\sum|s_i|+|S|)\)

// Trie+Kmp,多模式串匹配
struct ACAutomaton {static constexpr int N = 1e6 + 10;int ch[N][26], fail[N], cntNodes;int cnt[N];ACAutomaton() {cntNodes = 1;}void insert(string s) {int u = 1;for (auto c : s) {int &v = ch[u][c - 'a'];if (!v) v = ++cntNodes;u = v;}cnt[u]++;}void build() {fill(ch[0], ch[0] + 26, 1);queue<int> q;q.push(1);while (!q.empty()) {int u = q.front();q.pop();for (int i = 0; i < 26; i++) {int &v = ch[u][i];if (!v)v = ch[fail[u]][i];else {fail[v] = ch[fail[u]][i];q.push(v);}}}}LL query(string t) {LL ans = 0;int u = 1;for (auto c : t) {u = ch[u][c - 'a'];for (int v = u; v && ~cnt[v]; v = fail[v]) {ans += cnt[v];cnt[v] = -1;}}return ans;}
};

回文自动机 PAM(回文树)

应用:

  1. 本质不同的回文串个数:\(idx - 2\)
  2. 回文子串出现次数。

对于一个字符串 \(s\),它的本质不同回文子串个数最多只有 \(|s|\) 个,那么,构造 \(s\) 的回文树的时间复杂度是 \(\mathcal O(|s|)\)

struct PalindromeAutomaton {constexpr static int N = 5e5 + 10;int tr[N][26], fail[N], len[N];int cntNodes, last;int cnt[N];string s;PalindromeAutomaton(string s) {memset(tr, 0, sizeof tr);memset(fail, 0, sizeof fail);len[0] = 0, fail[0] = 1;len[1] = -1, fail[1] = 0;cntNodes = 1;last = 0;this->s = s;}void insert(char c, int i) {int u = get_fail(last, i);if (!tr[u][c - 'a']) {int v = ++cntNodes;fail[v] = tr[get_fail(fail[u], i)][c - 'a'];tr[u][c - 'a'] = v;len[v] = len[u] + 2;cnt[v] = cnt[fail[v]] + 1;}last = tr[u][c - 'a'];}int get_fail(int u, int i) {while (i - len[u] - 1 <= -1 || s[i - len[u] - 1] != s[i]) {u = fail[u];}return u;}
};

后缀自动机 SAM

定义 \(|\Sigma|\) 是字符集的大小,复杂度为 \(\mathcal O(N\log |\Sigma|)\)

// 有向无环图
struct SuffixAutomaton {static constexpr int N = 1e6;struct node {int len, link, nxt[26];int siz;} t[N << 1];int cntNodes;SuffixAutomaton() {cntNodes = 1;fill(t[0].nxt, t[0].nxt + 26, 1);t[0].len = -1;}int extend(int p, int c) {if (t[p].nxt[c]) {int q = t[p].nxt[c];if (t[q].len == t[p].len + 1) {return q;}int r = ++cntNodes;t[r].siz = 0;t[r].len = t[p].len + 1;t[r].link = t[q].link;copy(t[q].nxt, t[q].nxt + 26, t[r].nxt);t[q].link = r;while (t[p].nxt[c] == q) {t[p].nxt[c] = r;p = t[p].link;}return r;}int cur = ++cntNodes;t[cur].len = t[p].len + 1;t[cur].siz = 1;while (!t[p].nxt[c]) {t[p].nxt[c] = cur;p = t[p].link;}t[cur].link = extend(p, c);return cur;}
};

子序列自动机

对于给定的长度为 \(n\) 的主串 \(s\) ,以 \(\mathcal O(n)\) 的时间复杂度预处理、\(\mathcal O(m + \log \textrm{size:}s)\) 的复杂度判定长度为 \(m\) 的询问串是否是主串的子序列。

自动离散化、自动类型匹配封装

template<class T> struct SequenceAutomaton {vector<T> alls;vector<vector<int>> ver;SequenceAutomaton(auto in) {for (auto &i : in) {alls.push_back(i);}sort(alls.begin(), alls.end());alls.erase(unique(alls.begin(), alls.end()), alls.end());ver.resize(alls.size() + 1);for (int i = 0; i < in.size(); i++) {ver[get(in[i])].push_back(i + 1);}}bool count(T x) {return binary_search(alls.begin(), alls.end(), x);}int get(T x) {return lower_bound(alls.begin(), alls.end(), x) - alls.begin();}bool contains(auto in) {int at = 0;for (auto &i : in) {if (!count(i)) {return false;}auto j = get(i);auto it = lower_bound(ver[j].begin(), ver[j].end(), at + 1);if (it == ver[j].end()) {return false;}at = *it;}return true;}
};

朴素封装

原时间复杂度中的 \(\textrm{size:}s\) 需要手动设置。类型需要手动设置。

struct SequenceAutomaton {vector<vector<int>> ver;SequenceAutomaton(vector<int> &in, int size) : ver(size + 1) {for (int i = 0; i < in.size(); i++) {ver[in[i]].push_back(i + 1);}}bool contains(vector<int> &in) {int at = 0;for (auto &i : in) {auto it = lower_bound(ver[i].begin(), ver[i].end(), at + 1);if (it == ver[i].end()) {return false;}at = *it;}return true;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/945221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

边缘计算与AI:移动端设计软件的实时性能突破 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

标注工具--抹除目标

恩,chatgpt帮我写的标注抹除的工具 import cv2 import numpy as np import argparse import os """ 左键拖动 框选区域 左键单击 粘贴选区 z 撤销上一次操作 c 取消当前选区 s 手动保存 n 自动保存当前…

1024程序员节福利!参与互动,5分钟赢好礼!

Hi 程序员朋友们! 敲得了代码,扛得住需求,也该在 1024 这个专属节日里,给自己拆份“技术人专属福利”啦~ 作为深耕开源数据库的 IvorySQL,今年 1024 不想搞复杂玩法——2 种方式,轻松参与,即可获得 IvorySQL 周…

具身智能/智能体 定义

1. 具身智能智能并非一个孤立于身体的大脑计算过程,而是源于身体与环境的实时交互。智能、知觉和行动是一个不可分割的整体。 一个系统必须拥有“身体”(可以是实体机器人,也可以是虚拟环境中的化身),并通过这个身…

【数据挖掘】基于随机森林回归模型的二手车价格预测分析(信息集+源码)

【数据挖掘】基于随机森林回归模型的二手车价格预测分析(信息集+源码)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: …

实用指南:flink批处理-水位线

实用指南:flink批处理-水位线2025-10-24 13:24 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importan…

字符串模式匹配算法 KMP

子串与子序列中文名称 常见英文名称 解释子串 \(\tt substring\) 连续的选择一段字符(可以全选、可以不选)组成的新字符串子序列 \(\tt subsequence\) 从左到右取出若干个字符(可以不取、可以全取、可以不连续)组成…

Z函数(扩展 KMP)

Z函数(扩展 KMP) 获取字符串 \(s\) 和 \(s[i,n-1]\) (即以 \(s[i]\) 开头的后缀)的最长公共前缀(LCP)的长度,总复杂度 \(\mathcal O(N)\)。 vector<int> zFunction(string s) {int n = s.size();vector&l…

常用例题

常用例题 题意:在一篇文章(包含大小写英文字母、数字、和空白字符(制表/空格/回车))中寻找 \({\tt helloworld}\)(任意一个字母的大小写都行)的子序列出现了多少次,输出结果对 \(10^9+7\) 的余数。 字符串 DP …

2025年环评公司权威推荐排行榜,环评手续,环评报告,环评验收,专业高效服务助力企业合规发展

2025年环评公司权威推荐排行榜,环评手续,环评报告,环评验收,专业高效服务助力企业合规发展 一、行业背景与发展趋势 随着中国生态文明建设的深入推进,环境保护法律法规体系日益完善,环境影响评价作为建设项目环境…

2025年棒球帽厂家推荐排行榜,运动棒球帽,时尚棒球帽,定制棒球帽,防晒棒球帽公司精选榜单

2025年棒球帽厂家推荐排行榜:运动、时尚、定制与防晒棒球帽公司精选榜单 行业背景与发展趋势 棒球帽作为兼具功能性与时尚性的头部配饰,近年来在全球市场持续保持增长态势。随着运动休闲风的盛行和个性化需求的提升,…

常见结论与例题

常见结论 题意:(区间移位问题)要求将整个序列左移/右移若干个位置,例如,原序列为 \(A=(a_1, a_2, \dots, a_n)\) ,右移 \(x\) 位后变为 \(A=(a_{x+1}, a_{x+2}, \dots, a_n,a_1,a_2,\dots, a_x)\) 。 区间的端点…

单芯片方案分享-CH336F-USB拓展坞+百兆网卡+读卡器+100W快充芯片

CH336F是符合USB2.0协议规范的 3端口HUB、USB高速读卡器、USB PD快充和USB转以太网四合一控制器芯片,该芯片集成 3口USB HUB、USB高速SD卡读卡器、USB PD快充和USB百兆以太网扩展功能。简介 CH336F是符合USB2.0协议规…

于状压的线性 RMQ 算法

基于状压的线性 RMQ 算法 严格 \(\mathcal O(N)\) 预处理,\(\mathcal O(1)\) 查询。 template<class T, class Cmp = less<T>> struct RMQ {const Cmp cmp = Cmp();static constexpr unsigned B = 64;usi…

Flink编程模型 - 详解

Flink编程模型 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "…

工业4.0下的边缘存储设计:材料就地处理,响应更快更安全

工业4.0下的边缘存储设计:材料就地处理,响应更快更安全pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

服务器关机用halt、poweroff还是shutdown -h now?一文帮你说明

我们需要对服务器进行关机的时候,选择必要的关机命令是非常重要的,本文将帮你说明linux系统中halt、poweroff及shutdown -h now 三个命令的区别并描述底层原理 一. halt功能:停止系统运行,但不一定关闭电源。行为:…

KD Tree

KD Tree 在第 \(k\) 维上的单次查询复杂度最坏为 \(\mathcal O(n^{1-k^{-1}})\)。 struct KDT {constexpr static int N = 1e5 + 10, K = 2;double alpha = 0.725;struct node {int info[K];int mn[K], mx[K];} tr[N];…

小波矩阵树:高效静态区间第 K 大查询

小波矩阵树:高效静态区间第 K 大查询 手写 bitset 压位,以 \(\mathcal O(N \log N)\) 的时间复杂度和 \(\mathcal O(N + \frac{N \log N}{64})\) 的空间建树后,实现单次 \(\mathcal O(\log N)\) 复杂度的区间第 \(k…

Seata用法

目录AT模式TCCSAGA模式参考资料 AT模式在Springboot启动程序加上,@EnableAutoDataSourceProxy 确保数据源被代理 在全局事务启动的方法上加 @GlobalTransactional 分支事务代码无需做任何处理。TCC 实现类加上 @Local…