P3808 AC 自动机(简单版)
这两题始终做完 P5357 【模板】AC 自动机 这题的基础上做的
P3808 AC 自动机(简单版)
更改一下范围和打印内容。
#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)
同上修改
#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;
}