前缀函数和KMP算法
前缀函数( 函数)
定义
border :若字符串
前缀函数 :前缀函数
实现
vector<int> prefix_function(string s) {
int n = (int)s.length();
vector<int> pi;
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j && s[i] != s[j]) j = pi[j - 1];
if (s[i] == s[j]) j++;
pi[i] = j;
}
return pi;
}
前缀函数的应用
一 、模式匹配(KMP算法)
给定一个文本串
将模式串与文本串拼接,在中间加一个分隔符,变为字符串
二 、字符串的周期
对字符串
若
可以借助前缀函数得到
三 、统计每个前缀的出现次数
考虑位置
所以我们可以通过以下方法计算答案 。
for (int i = 0; i < n; i++) ans[pi[i]]++;
for (int i = n - 1; i > 0; i--) ans[pi[i-1]] += ans[i];
for (int i = 0; i < n; i++) ans[i]++;
四 、一个字符串中本质不同子串的数目
考虑向一个字符串
构造字符串
五 、字符串压缩(字符串的整周期)
给定一个长度为
计算
六 、根据前缀函数构建一个自动机
重新考虑计算前缀函数的问题,我们先前使用构造字符串
例如计算字符串
第
先计算
自动机部分代码
void compute_automaton(string s, vector<vector<int>> &aut) {
s += '#';
int n = (int)s.size();
vector<int> pi = prefix_function(s);
aut.assign(n, vector<int>(26));
for (int i = 0; i < n; i++) {
for (int c = 0; c < 26; c++) {
if (i > 0 && 'a' + c != s[i]) aut[i][c] = aut[pi[i - 1]][c];
else aut[i][c] = i + ('a' + c == s[i]);
}
}
}
我们实际要计算的是有多少个位置的前缀函数值等于
设
初始条件
转移
最终答案就是
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】