HDU 2222 Keywords Search(AC自动机)

来源:互联网 发布:服务器数据库版本 编辑:程序博客网 时间:2024/04/30 20:06

AC自动机模板题

#include <iostream>#include <string>#include <cstring>#include <queue>using namespace std;struct node{int count;  //记录以此为终点的单词的个数node *fail;node *son[26];};queue<node *>q;node word[500010];int e;char str[1000005];//创建一个新结点node *newnode(){word[++e].count = 0;word[e].fail = NULL;for (int i = 0; i < 26; i++)word[e].son[i] = NULL;return &word[e];}void add(string s,node *root){node *now = root;int len = s.size();for (int i = 0; i < len; i++){int id = s[i] - 'a';//如果该儿子节点不存在,新建一个结点if (now->son[id] == NULL){now->son[id] = newnode();}//如果该儿子结点是单词的结束位置,单词数量加1if (i == len - 1)now->son[id]->count++;now = now->son[id];}}//用BFS的方法获得fail值void ac_automation(node *root){node *now = root;//把根结点的fail设为NULLnow->fail = NULL;q.push(now);while (!q.empty()){now = q.front();q.pop();//把now的26个儿子中不为空儿子的fail填充for (int i = 0; i < 26; i++){//如果是根的子节点,则fail指向rootif (now == root){if (now->son[i] != NULL){now->son[i]->fail = root;q.push(now->son[i]);}}//否则沿着fail向上搜索,直到找到一个结点,该节点的子节点id存在,则now->son[i]->fail 便指向该子节点//若找不到符合要求的结点,则now->son[i]->fail 便指向rootelse{if (now->son[i] != NULL){node *temp = now->fail;while (temp != NULL){if (temp->son[i] != NULL){now->son[i]->fail = temp->son[i];break;}temp = temp->fail;}if (temp == NULL)now->son[i]->fail = root;q.push(now->son[i]);}}//end of else}//end of for}//end of while}int solve(char *s,node *root){node *now = root;int len = strlen(s), i = 0, ans = 0;for (i = 0; i < len; i++){int id = s[i] - 'a';//如果id儿子不存在,则沿着fail找到存在id儿子的结点while (now->son[id] == NULL&&now != root)now = now->fail;//如果没找到,把就从root开始,否则就从id儿子开始now = (now->son[id] == NULL) ? root : now->son[id];node *temp = now;while (temp != root){ans += temp->count;temp->count = 0;temp = temp->fail;}}return ans;}int main(){int t;cin >> t;while (t--){int n;cin >> n;string s;e = -1;node *root = newnode();for (int i = 0; i < n; i++){cin >> s;add(s,root);}scanf("%s", str);ac_automation(root);cout << solve(str, root) << endl;}}

0 0
原创粉丝点击