这两题始终做完 P5357 【模板】AC 自动机 这题的基础上做的
P3808 AC 自动机(简单版)


更改一下范围和打印内容。
cpp
#include<bits/stdc++.h>
#define ll long long
#define endl "\n"
using namespace std;
const int MAX0 = 2e6 + 3;
const int MAXN = 2e6 + 3;
struct {
int trie[MAX0][26], cnt = 0;//字典树(a~z)
int output[MAX0]; // 输出标记,及以此位置结尾的的模式串有多少个;(很少用)
int fail[MAX0];//失配指针
int ins[MAXN], insi;//输入第i个模式串的结尾位置vector<int> ins;
int time[MAX0]; // 在匹配串中,这个位置出现过多少次;
// 初始化
void init() {
memset(trie, 0, sizeof(trie));
memset(fail, 0, sizeof(fail));
memset(ins, 0, sizeof(ins));
memset(output, 0, sizeof(output));
memset(time, 0, sizeof(time));
cnt = 0, insi = 0;
}
void inittime() {
memset(time, 0, sizeof(time));
}
//插入模式串,建立tire树(字典树)
void insert(string s) {
int sn = s.size();
int i = 0;
for (int z = 0; z < sn; z++) {
int j = s[z] - 'a';
if (!trie[i][j]) {
trie[i][j] = ++cnt;
}
i = trie[i][j];
}
ins[insi++] = i;
output[i]++;
}
// 构建失配指针+建立直通表(优化trie)(避免绕圈)
void build() {
queue<int> q;
for (int j = 0; j < 26; j++) {
if (trie[0][j] != 0) {
fail[trie[0][j]] = 0;
q.push(trie[0][j]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int j = 0; j < 26; j++) {
if (trie[u][j] != 0) {
fail[trie[u][j]] = trie[fail[u]][j];
q.push(trie[u][j]);
}
else {
trie[u][j] = trie[fail[u]][j];
}
}
}
}
//建立fail的反树,避免遍历文章时绕圈
void opposedfail() {
vector<vector<int>> opposed(cnt+1, vector<int>());
vector<bool> visited(cnt + 1, false);
for (int i = 1; i <= cnt; i++) {
opposed[fail[i]].push_back(i);
}
stack<int> q;
q.push(0);
while (!q.empty()) {
int i = q.top();
if (!visited[i]) {
visited[i] = true;
for (int j = 0; j < opposed[i].size(); j++) {
q.push(opposed[i][j]);
}
}
else {
time[fail[i]] += time[i];
q.pop();
}
}
}
//匹配串匹配
void search(string s) {
int sn = s.size();
int i = 0;
for (int z = 0; z < sn; z++) {
int j = s[z] - 'a';
time[trie[i][j]]++;
i = trie[i][j];
}
opposedfail();
}
}AC;
void solve() {
int n;
AC.init();
cin >> n;
string s;
for (int i = 0; i < n; i++) {
cin >> s;
AC.insert(s);
}
AC.build();
cin >> s;
AC.search(s);
int ans = 0;
for (int i = 0; i < AC.insi; i++) {
if (AC.time[AC.ins[i]]) {
ans++;
}
}
cout << ans << endl;
return;
}
int main(){
ios::sync_with_stdio(false); // 禁用同步
std::cin.tie(nullptr),std::cout.tie(nullptr); // 解除cin与cout绑定
int t = 1;
//cin >> t;
while (t--) {
solve();
}
return 0;
}
P3796 AC 自动机(简单版 II)

同上修改
cpp
#include<bits/stdc++.h>
#define ll long long
#define endl "\n"
using namespace std;
const int MAX0 = 2e4 + 3;
const int MAXN = 150 + 3;
struct {
int trie[MAX0][26], cnt = 0;//字典树(a~z)
int output[MAX0]; // 输出标记,及以此位置结尾的的模式串有多少个;(很少用)
int fail[MAX0];//失配指针
int ins[MAXN], insi;//输入第i个模式串的结尾位置vector<int> ins;
int time[MAX0]; // 在匹配串中,这个位置出现过多少次;
// 初始化
void init() {
memset(trie, 0, sizeof(trie));
memset(fail, 0, sizeof(fail));
memset(ins, 0, sizeof(ins));
memset(output, 0, sizeof(output));
memset(time, 0, sizeof(time));
cnt = 0, insi = 0;
}
void inittime() {
memset(time, 0, sizeof(time));
}
//插入模式串,建立tire树(字典树)
void insert(string s) {
int sn = s.size();
int i = 0;
for (int z = 0; z < sn; z++) {
int j = s[z] - 'a';
if (!trie[i][j]) {
trie[i][j] = ++cnt;
}
i = trie[i][j];
}
ins[insi++] = i;
output[i]++;
}
// 构建失配指针+建立直通表(优化trie)(避免绕圈)
void build() {
queue<int> q;
for (int j = 0; j < 26; j++) {
if (trie[0][j] != 0) {
fail[trie[0][j]] = 0;
q.push(trie[0][j]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int j = 0; j < 26; j++) {
if (trie[u][j] != 0) {
fail[trie[u][j]] = trie[fail[u]][j];
q.push(trie[u][j]);
}
else {
trie[u][j] = trie[fail[u]][j];
}
}
}
}
//建立fail的反树,避免遍历文章时绕圈
void opposedfail() {
vector<vector<int>> opposed(cnt+1, vector<int>());
vector<bool> visited(cnt + 1, false);
for (int i = 1; i <= cnt; i++) {
opposed[fail[i]].push_back(i);
}
stack<int> q;
q.push(0);
while (!q.empty()) {
int i = q.top();
if (!visited[i]) {
visited[i] = true;
for (int j = 0; j < opposed[i].size(); j++) {
q.push(opposed[i][j]);
}
}
else {
time[fail[i]] += time[i];
q.pop();
}
}
}
//匹配串匹配
void search(string s) {
int sn = s.size();
int i = 0;
for (int z = 0; z < sn; z++) {
int j = s[z] - 'a';
time[trie[i][j]]++;
i = trie[i][j];
}
opposedfail();
}
}AC;
int n;
void solve() {
AC.init();
vector<string >f(n);
for (int i = 0; i < n; i++) {
cin >> f[i];
AC.insert(f[i]);
}
AC.build();
string s;
cin >> s;
AC.search(s);
int max_f = 0;
for (int i = 0; i < AC.insi; i++) {
max_f = max(AC.time[AC.ins[i]], max_f);
}
cout << max_f << endl;
for (int i = 0; i < AC.insi; i++) {
if (AC.time[AC.ins[i]] == max_f) {
cout << f[i] << endl;
}
}
return;
}
int main(){
ios::sync_with_stdio(false); // 禁用同步
std::cin.tie(nullptr),std::cout.tie(nullptr); // 解除cin与cout绑定
int t = 1;
//cin >> t;
while (cin>>n) {
if (n == 0) {
break;
}
solve();
}
return 0;
}