Aho-Corasick 自动机

来源:互联网 发布:制衣打飞软件 编辑:程序博客网 时间:2024/05/18 00:03

参考:《算法竞赛入门经典-训练指南》


在模式匹配问题中,如果模板有多个,KMP 算法就不太适合了


1、UVALive 4670 Dominating Patterns

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <map>#include <queue>#include <stack>#include <set>#include <bitset>#include <ctime>#include <cctype>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> Pair;const int INF = 0x7fffffff;const int maxn = 1e6 + 10;map<string, int> mp;struct AC_Automata {    int ch[maxn][26], fail[maxn], val[maxn], last[maxn];    int cnt[160];    int size;    void init() {        size = 1;        memset(ch[0], 0, sizeof(ch[0]));        memset(cnt, 0, sizeof(cnt));        mp.clear();    }    int idx(char c) { return c - 'a'; };    void insert(char* s, int _val);    void find(char* T);    void cnt_time(int j);    void get_fail(void);};char text[maxn], P[160][80];int N;AC_Automata ac;int main() {#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H_    while (scanf("%d", &N) != EOF && N != 0) {        ac.init();        for (int i = 0; i < N; ++i) {            scanf("%s", P[i]);            ac.insert(P[i], i + 1);        }        ac.get_fail();        scanf("%s", text);        ac.find(text);        int Max = 0;        for (int i = 1; i <= N; ++i) {            Max = max(Max, ac.cnt[i]);        }        printf("%d\n", Max);        for (int i = 0; i < N; ++i) {            if (ac.cnt[mp[P[i]]] == Max) {                printf("%s\n", P[i]);            }        }    }    return 0;}void AC_Automata::get_fail(void) {    queue<int> q;    fail[0] = 0;    for (int c = 0; c < 26; ++c) {        int u = ch[0][c];        if (u) {            fail[u] = 0; q.push(u); last[u] = 0;        }    }    while (!q.empty()) {        int f = q.front(); q.pop();        for (int c = 0; c < 26; ++c) {            int u = ch[f][c];            if (!u) {                ch[f][c] = ch[fail[f]][c];                continue;            }            q.push(u);            int v = fail[f];            fail[u] = ch[v][c];            last[u] = val[fail[u]] ? fail[u] : last[fail[u]];        }    }}void AC_Automata::find(char* T) {    int len = strlen(T);    int j = 0;    for (int i = 0; i < len; ++i) {        int c = idx(T[i]);        while (j && !ch[j][c]) {            j = fail[j];        }        j = ch[j][c];        if (val[j]) {            cnt_time(j);        } else if (last[j]) {            cnt_time(last[j]);        }    }}void AC_Automata::cnt_time(int j) {    if (j) {        ++cnt[val[j]];        cnt_time(last[j]);    }}void AC_Automata::insert(char* s, int _val) {    int u = 0, len = strlen(s);    for (int i = 0; i < len; ++i) {        int c = idx(s[i]);        if (!ch[u][c]) {            memset(ch[size], 0, sizeof(ch[size]));            val[size] = 0, ch[u][c] = size++;        }        u = ch[u][c];    }    val[u] = _val; mp[s] = _val;}





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 裴先生每天都在撒娇求和 空间逃荒:团宠小尼姑路子野 别慌,学霸老爹和我一起穿越了 薄先生突然黏她上瘾 团宠崽崽是只桃花精 我那老板柔弱不能自理 反派小媳妇的逆袭指南 我有一个大佬群 二婚后,我在豪门扮柔弱 诸天仙神热搜:主神老婆竟是魔尊 团宠小福妻又娇又软 替嫁医妃有空间 重生之农门贵夫 野性偏爱 嫁给病弱太子后我躺赢了 咸鱼娘娘一心只想翻墙 救命!破产后高冷总裁处处招惹我 冷酷将军每天都想要贴贴 何以赎光 甜腻!病娇傅少竟然暗恋我! 天价萌妻:偏执帝少心尖宠 有读心术后,战神把娘子宠上天 穿书后,我刷错了反派的好感度 摄政王怀里的团宠美人娇又软 满级千金不想掉马 女帝她就是个卖药的! 华娱激荡年代 她来看我的演唱会 快穿:娇养反派大佬做替身 不努力种田就要和相公继承皇位了 穿书末世之我是金手指 转生恶少后的魔幻日常 穿书后我成了反派男二的铁血妈粉 带着超市重返年代 新婚夜,我被冷冰冰的王爷读心了 修仙女配拿了反派剧本 影后的假面童话 克死前夫后我成了心软的神 新婚夜,我治好了失明太子的隐疾 沦陷野玫瑰 完球!我的崽居然是反派