[kuangbin带你飞]专题17:A

来源:互联网 发布:所有香烟条形码数据库 编辑:程序博客网 时间:2024/06/05 16:53

AC自动机模版题

#include<iostream>#include<queue>#include<algorithm>#include<cmath>#include<cstdio>#include<string>#include<cstring>using namespace std;//可优化为数组形式struct node{    node* next[26];    node* fail;    int value;    node() {        for(int i = 0; i < 26; i++) next[i] = NULL;        fail = NULL;        value = 0;    }};node* root;queue<node*> q;void insert(string s) {    int l =(int)s.length();    node* p = root;    for(int i = 0; i < l; i++) {        int id = s[i]-'a';        if(p->next[id] == NULL) p->next[id] = new node();        p = p->next[id];    }    p->value++; //作为一个单词匹配的标记 }void setfail() {    q.push(root);    while(!q.empty()) {        node* now = q.front(); q.pop();//取出下一个,出队        for(int i = 0 ; i < 26; i++) if(now->next[i]) {//节点存在,为它构建fail指针            node *p = now->fail;            while(p && !p->next[i]) p = p->fail; //如果now为root,则fail为NULL            now->next[i]->fail = p ? p->next[i] : root;//赋值            q.push(now->next[i]);//入队        }       }}int ac(string s) {    int l = (int)s.length();    node* now = root;    int cnt = 0;    for(int i = 0; i < l; i++) {        int id = (int)(s[i] - 'a');        while(now && !now->next[id]) now = now->fail;//找到匹配的位置,//千万不能写反        now = now ? now->next[id] : root;        for(node* p = now; p ; p= p->fail) if(p->value > 0) {                cnt += p->value;                p->value = 0;        }    }    return cnt;}void clear(node* p) {    for(int i = 0; i < 26; i++) if(p->next[i]) clear(p->next[i]);    delete p;}int main() {    //freopen("a.in", "r", stdin);    ios::sync_with_stdio(false);    int T; cin >> T;    string s;    while(T--) {        //初始化        root = new node();        int N; cin >> N;        while(N--) {            cin >> s;            insert(s);        }        cin >> s;        setfail();        cout << ac(s) << endl;        clear(root);    }    return 0;}
原创粉丝点击