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;
}
相关推荐
倒头就睡的小比特5 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼5 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光5 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark5 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her15 天前
并查集-听课笔记
笔记·算法·并查集
码流子5 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven5 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark5 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218615 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法