P3808 AC 自动机(简单版)

这两题始终做完 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;
}
相关推荐
Xの哲學14 分钟前
Linux二层转发: 从数据包到网络之桥的深度解剖
linux·服务器·算法·架构·边缘计算
我也要当昏君1 小时前
计算机组成原理
算法
Fiona-Dong1 小时前
Louvain 算法
python·算法
维构lbs智能定位1 小时前
蓝牙信标、UWB等主流室内定位无线技术的参数对比、核心算法和选型指南详解(二)
算法·蓝牙信标·uwb·主流室内定位无线技术
灰灰勇闯IT2 小时前
【探索实战】Kurator多集群统一应用分发实战:从环境搭建到业务落地全流程
算法
鱼在树上飞2 小时前
乘积最大子数组
算法
H_z___3 小时前
Codeforces Round 1070 (Div. 2) A~D F
数据结构·算法
自学小白菜3 小时前
每周刷题 - 第三周 - 双指针专题 - 02
python·算法·leetcode
杜子不疼.3 小时前
【LeetCode76_滑动窗口】最小覆盖子串问题
算法·哈希算法
ComputerInBook3 小时前
代数基本概念理解——特征向量和特征值
人工智能·算法·机器学习·线性变换·特征值·特征向量