一、KMP
首先第一个算法是KMP字符串匹配,这是个很有难度的算法。
字符串模式匹配:可以简单地理解为在目标(字符串)中寻找一个给定的模式(也是字符串),返回目标和模式匹配的第一个子串的首字符位置。通常目标串比较大,而模式串则比较短小。
KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)。
KMP的算法思想还是比较容易理解的,但是解释起来会比较抽象,(其实是我不会解释。) 所以就插入一个大学学长写的博客吧!
字符串 KMP算法与AC自动机算法
例题
s串中查找p串,输出起始下标
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e6 + 10;
int lenp, lens;
char p[N], s[N];
int ne[N];
int main() {
scanf("%d %s", &lenp, p + 1);
scanf("%d %s", &lens, s + 1);
for (int i = 2, j = 0; i <= lenp; i++) {
while (j && p[j + 1] != p[i]) j = ne[j];
if (p[j + 1] == p[i]) j++;
ne[i] = j;
}
for (int i = 1, j = 0; i <= lens; i++) {
while (j && p[j + 1] != s[i]) j = ne[j];
if (p[j + 1] == s[i]) j++;
if (j == lenp)
{
printf("%d ", i - lenp);
j = ne[j];
}
}
return 0;
}
二、Trie
一种高效存储和查找字符串集合的数据结构。
例题1
维护一个字符串集合,支持两种操作:
“I x”向集合中插入一个字符串x;
“Q x”询问一个字符串在集合中出现了多少次。
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
int son[N][26], cnt[N], idx;
char str[N];
void insert(char str[]) {
int p = 0;
for (int i = 0; str[i]; i++) {
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
cnt[p]++;
}
int query(char str[]) {
int p = 0;
for (int i = 0; str[i]; i++) {
int u = str[i] - 'a';
if (!son[p][u]) return 0;
p = son[p][u];
}
return cnt[p];
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
char op[2];
scanf("%s %s", op, str);
if (op[0] == 'I') insert(str);
else printf("%d\n", query(str));
}
return 0;
}
例题2
在给定的N个整数 A 1 , A 2 … … A N A_{1},A_{2}……A_{N} A</