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;
}
相关推荐
Jayden_Ruan5 小时前
C++十进制转二进制
数据结构·c++·算法
Haooog5 小时前
98.验证二叉搜索树(二叉树算法题)
java·数据结构·算法·leetcode·二叉树
Macre Aegir Thrym6 小时前
MINIST——SVM
算法·机器学习·支持向量机
Young_Zn_Cu7 小时前
LeetCode刷题记录(持续更新中)
算法·leetcode
天选之女wow7 小时前
【代码随想录算法训练营——Day31】贪心算法——56.合并区间、738.单调递增的数字、968.监控二叉树
算法·leetcode·贪心算法
lixinnnn.7 小时前
贪心:火烧赤壁
数据结构·c++·算法
小小前端_我自坚强7 小时前
前端算法相关详解
前端·算法
前端 贾公子8 小时前
《Vuejs设计与实现》第 5 章(非原始值响应式方案)下 Set 和 Map 的响应式代理
数据结构·算法
WWZZ20259 小时前
ORB_SLAM2原理及代码解析:SetPose() 函数
人工智能·opencv·算法·计算机视觉·机器人·自动驾驶