P3375 【模板】KMP 字符串匹配
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e6 + 10;
char s[N], t[N];
int n, m;
int bd[N];
int main(){
scanf("%s%s", (s+1), (t+1));
n = strlen(s+1);
m = strlen(t+1);
int j = 0;
bd[1] = 0;
for(int i = 2; i <= m; i++){
while(j && t[j+1] != t[i]){
j = bd[j];
}
if(t[j+1] == t[i]){
j++;
}
bd[i] = j;
}
j = 0;
for(int i = 1; i <= n; i++){
while(j && t[j+1] != s[i]){
j = bd[j];
}
if(t[j+1] == s[i]){
j++;
}
if(j == m){
printf("%d\n", i-m+1);
j = bd[j];
}
}
for(int i = 1; i <= m; i++){
printf("%d ", bd[i]);
}
puts("");
return 0;
}
142. 前缀统计
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
int n, m;
char str[M];
struct node{
int num;
int son[26];
}tr[M];
int tcnt = 1;
void insert(char *s){
int len = strlen(s+1);
int p = 1;
for(int i = 1; i <= len; i++){
int j = s[i] - 'a';
if(!tr[p].son[j]){
tr[p].son[j] = ++tcnt;
}
p = tr[p].son[j];
}
tr[p].num++;
}
int query(char *s){
int len = strlen(s+1);
int p = 1;
int tans = 0;
for(int i = 1; i <= len; i++){
int j = s[i] - 'a';
if(!tr[p].son[j]){
return tans;
}
p = tr[p].son[j];
tans += tr[p].num;
}
return tans;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%s", str+1);
insert(str);
}
for(int i = 1; i <= m; i++){
scanf("%s", str+1);
printf("%d\n", query(str));
}
return 0;
}
P3796 【模板】AC 自动机(加强版)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N = 11000;
int n;
char s[160][80], t[1000010];
int cnt[160];
int ans;
int son[N][26], num[N], fal[N], tcnt;
int New(){
tcnt++;
for(int i = 0; i < 26; i++){
son[tcnt][i] = 0;
}
num[tcnt] = 0;
fal[tcnt] = 0;
return tcnt;
}
void insert(int x){
int len = strlen(s[x]+1);
int p = 1;
for(int i = 1; i <= len; i++){
int j = s[x][i] - 'a';
if(!son[p][j]){
son[p][j] = New();
}
p = son[p][j];
}
num[p] = x;
}
queue<int> q;
void build(){
for(int i = 0; i < 26; i++){
son[0][i] = 1;
}
fal[1] = 0;
q.push(1);
while(!q.empty()){
int x = q.front();
q.pop();
for(int i = 0; i < 26; i++){
if(son[x][i]){
fal[son[x][i]] = son[fal[x]][i];
q.push(son[x][i]);
}else{
son[x][i] = son[fal[x]][i];
}
}
}
}
void query(char *str){
int len = strlen(str+1);
int p = 1;
for(int i = 1; i <= len; i++){
int j = str[i] - 'a';
p = son[p][j];
for(int k = p; k; k = fal[k]){
cnt[num[k]]++;
}
}
}
int main(){
while(scanf("%d", &n), n){
tcnt = 0;
New();
for(int i = 1; i <= n; i++){
cnt[i] = 0;
scanf("%s", (s[i]+1));
insert(i);
}
build();
scanf("%s", (t+1));
query(t);
ans = 0;
for(int i = 1; i <= n; i++){
ans = max(ans, cnt[i]);
}
printf("%d\n", ans);
for(int i = 1; i <= n; i++){
if(ans == cnt[i]){
printf("%s\n", (s[i]+1));
}
}
}
return 0;
}
P5357 【模板】AC 自动机(二次加强版)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int N = 2e5 + 10, M = 2e6 + 10;
int n;
char s[N], t[M];
int cnt[N];
int bl[M];
int son[M][26], fal[M], tcnt = 1;
vector<int> g[M];
void insert(int x){
int len = strlen(s+1);
int p = 1;
for(int i = 1; i <= len; i++){
int j = s[i] - 'a';
if(!son[p][j]){
son[p][j] = ++tcnt;
}
p = son[p][j];
}
bl[x] = p;
}
queue<int> q;
void build(){
for(int i = 0; i < 26; i++){
son[0][i] = 1;
}
fal[1] = 0;
q.push(1);
while(!q.empty()){
int x = q.front();
q.pop();
for(int i = 0; i < 26; i++){
if(son[x][i]){
fal[son[x][i]] = son[fal[x]][i];
g[son[fal[x]][i]].push_back(son[x][i]);
q.push(son[x][i]);
}else{
son[x][i] = son[fal[x]][i];
}
}
}
}
void query(char *str){
int len = strlen(str+1);
int p = 1;
for(int i = 1; i <= len; i++){
int j = str[i] - 'a';
p = son[p][j];
cnt[p]++;
// for(int k = p; k; k = fal[k]){
// cnt[k]++;
// }
}
}
void dfs(int x){
for(int y : g[x]){
dfs(y);
cnt[x] += cnt[y];
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%s", (s+1));
insert(i);
}
build();
scanf("%s", (t+1));
query(t);
dfs(1);
for(int i = 1; i <= n; i++){
printf("%d\n", cnt[bl[i]]);
}
return 0;
}
KMP 求最小循环节(AcWing 141. 周期)