hdu2222 ac自动机模板
2014-08-09 01:40
363 查看
题意:给出一系列字符串作为关键字,再给出一个字符串作为查询串,问查询串里包含多少关键字。
字符串匹配有kmp,保存大量字符串有字典树,所以当出现大量字符串需要匹配的情况,就有了ac自动机,这名字总让人想到一种很美好的歧义。。
就是数据插入字典树,构造自动机和把字符串放进去匹配三个基本操作把。
构造自动机规则如下:
如果某个节点的父节点就是根节点,那么这个节点的失败节点也就是根节点。
如果C的子节点中,有与A相同的节点B,则A的失败节点就是B
如果C的子节点中,没有与A相同的节点,且C就是根节点,则A的失败节点就是C
如果C的子节点中,没有与A相同的节点,但C不是根节点,则令C为C的失败节点,重复
查询规则如下:
在查找时,当前处在某个节点,往下无路可走时,那么就可以沿着fail指针跳到失败节点。
如果失败节点也无路可走,则跳到失败节点的失败节点,直至有路可走或者走到根节点为止。
思路就那么回事,真要写就纠结了。。
模板代码:
字符串匹配有kmp,保存大量字符串有字典树,所以当出现大量字符串需要匹配的情况,就有了ac自动机,这名字总让人想到一种很美好的歧义。。
就是数据插入字典树,构造自动机和把字符串放进去匹配三个基本操作把。
构造自动机规则如下:
如果某个节点的父节点就是根节点,那么这个节点的失败节点也就是根节点。
如果C的子节点中,有与A相同的节点B,则A的失败节点就是B
如果C的子节点中,没有与A相同的节点,且C就是根节点,则A的失败节点就是C
如果C的子节点中,没有与A相同的节点,但C不是根节点,则令C为C的失败节点,重复
查询规则如下:
在查找时,当前处在某个节点,往下无路可走时,那么就可以沿着fail指针跳到失败节点。
如果失败节点也无路可走,则跳到失败节点的失败节点,直至有路可走或者走到根节点为止。
思路就那么回事,真要写就纠结了。。
模板代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int maxn = 500010; char str[1000010]; struct ACAutomaton{ int next[maxn][26],fail[maxn],flag[maxn],last[maxn]; int num,root; int newnode() { memset(next[num],0,sizeof(next[num])); flag[num] = 0; return num++;//每次都加,故num为结点数 } void init() { num = 0; root = newnode(); } void insert(char *str) { int len = strlen(str); int now = root; for(int i = 0;i < len;i++) { int &tmp = next[now][str[i]-'a'];//&取地址 if(!tmp) tmp = newnode();//是空的那新建结点 now = tmp; } flag[now]++; } void getfail() { queue<int> q; fail[root] = root; for(int i = 0;i < 26;i++) { int u = next[root][i]; if(u)//头 { fail[u] = last[u] = 0; q.push(u); } } while(!q.empty()) { int now = q.front();q.pop(); for(int i = 0;i < 26;i++) { int u = next[now][i]; if(!u) //这个点的第i个儿子指向now的失败节点的第i个儿子 next[now][i] = next[fail[now]][i]; else { fail[u] = next[fail[now]][i];//u的失败节点指向fail[now]的第i个儿子 last[u] = flag[fail[u]] ? fail[u]:last[fail[u]];//后缀链接 q.push(u); } } } } int query(char *str){ int len = strlen(str); int now = root; int ret = 0; for(int i = 0;i < len;i++) { now = next[now][str[i]-'a']; int tmp = now; while(tmp != root && flag[tmp]) { ret += flag[tmp]; flag[tmp] = 0;//防止重复统计 tmp = last[tmp]; } } return ret; } }ac; int main(){ int k,n; scanf("%d",&k); while(k--) { ac.init(); scanf("%d",&n); for(int i = 0;i < n;i++) { scanf("%s",str); ac.insert(str); } ac.getfail();//类似kmp里的next scanf("%s",str); printf("%d\n",ac.query(str)); } return 0; }
相关文章推荐
- hdu2222 AC自动机入门 指针型模板
- AC自动机模板(hdu2222)
- hdu2222 ac自动机模板
- [AC自动机(模板题)] hdu2222 Keywords Search
- AC自动机模板 hdu2222
- HDU2222【AC自动机(基础·模板)】
- HDU2222 Keywords Search 【AC自动机模板题】
- hdu2222(ac自动机模板)
- Keywords Search---hdu2222(AC自动机 模板)
- AC自动机 模板 【HDU2222】 Keywords Search
- AC自动机模板(数组+指针)hdu2222
- ac自动机模板(hdu2222)
- ac自动机模板(hdu2222)
- HDU2222 AC自动机 入门模板
- AC自动机(1)--hdu2222(基本模板)
- 【HDU2222】【AC自动机模板 测烂为止】Keywords Search
- HDU2222_Keywords Search _AC自动机模板题
- HDU2222 Keywords Search(AC自动机模板)
- [hdu2222]ac自动机(模板)
- ac自动机模板hdu2222