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;
}
相关推荐
小欣加油20 小时前
leetcode56 合并区间
c++·算法·leetcode·职场和发展
lqqjuly20 小时前
前沿算法深度解析(二)
人工智能·算法·机器学习
徐小夕21 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei21 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld1 天前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi81 天前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
youngerwang1 天前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby1 天前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠1 天前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
无限码力1 天前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试