hdu 2222 Keywords Search(AC自动机入门题)

来源:互联网 发布:python读写数据txt 编辑:程序博客网 时间:2024/06/06 19:02

昨晚开始想学AC自动机,然后尽早看了看算导的KMP。。。以前看过,忘差不多了。

今天看了看一个学习AC自动机的文章,磕磕绊绊理解了。

trie的建立很随意,关键是失败指针这个概念。稍微有点抽象。这个指针的建立,用到了BFS,引用那个文章的话

“  假设有一个节点k,他的失败指针指向j。那么k,j满足这个性质:设root到j的距离为n,则从k之上的第n个节点到k所组成的长度为n的单词,与从root到j所组成的单词相同。对于每个节点,我们可以这样处理:设这个节点上的字母为C,沿着他父亲的失败指针走,直到走到一个节点,他的儿子中也有字母为C的节点。然后把当前节点的失败指针指向那个字目也为C的儿子。如果一直走到了root都没找到,那就把失败指针指向root,最开始,我们把root加入队列(root的失败指针显然指向自己),这以后我们每处理一个点,就把它的所有儿子加入队列,直到搞完。”

查找匹配数目的时候,如果发现不匹配的就沿着失败指针寻找,直到到根部为止。

因为失败指针走一次后再走就没有用了,可以标记下,下次就不用走了。

#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define BUG puts("here!!!")#define STOP system("pause")using namespace std;const int MAX_N = 26;const int MAX_NODE = 500010;struct NODE{int cnt;NODE *next[MAX_N], *fail;NODE(){cnt = 0;fail = NULL;memset(next, 0, sizeof(next));}}*head;void Build_trie(char *s,NODE *head){int len = strlen(s);for(int i=0; i<len; i++){int k = s[i] - 'a';if( head->next[k] == NULL )head->next[k] = new NODE();head = head->next[k];}head->cnt++;}queue<NODE*> q;void Build_fail(NODE *head){head->fail = NULL;q.push(head);while( !q.empty() ){NODE *now = q.front(); q.pop();for(int i=0; i<MAX_N; i++)if( now->next[i] ){NODE *p = now->fail;while( p ){if( p->next[i] ){now->next[i]->fail = p->next[i];break;}p = p->fail;}if( p == NULL )now->next[i]->fail = head;q.push(now->next[i]);}}}int AC_find(NODE *head, char *s){int len = strlen(s), sum = 0;NODE* p = head;for(int i=0; i<len; i++){int k = s[i] - 'a';while( p->next[k] == NULL && p != head )p = p->fail;p = p->next[k] == NULL ? head : p->next[k];NODE *tmp = p;while( tmp != head && tmp->cnt != -1 ){sum += tmp->cnt;tmp->cnt = -1;tmp = tmp->fail;}}return sum;}char s[1000005];char ss[100];int main(){int n, ncases;scanf("%d", &ncases);while( ncases-- ){head = new NODE();scanf("%d", &n);while( n-- ){scanf("%s", ss);Build_trie(ss, head);}Build_fail( head );scanf("%s", s);int sum = AC_find( head, s);printf("%d\n", sum);}return 0;}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑卡住了怎么办鼠标也点不动 幽灵行动荒野没有主线任务了怎么办 拼多多购买的东西下架了怎么办 电脑版的荒野行动玩的时候卡怎么办 欧洲卡车模拟2气压过低怎么办 word页眉和正文有段距离怎么办 酷派大神x7卡在开机界面怎么办 妹妹结婚跟领导请假不批怎么办 网页分享后不想显示连接网址怎么办 魔兽世界肉弹随从的任务断了怎么办 在美发店上班被小混混打了怎么办 孩子上四年级了不知道写作业怎么办 运动完第二天恶心想吐怎么办 吃减肥药皮肤变差了怎么办 生了孩子子宫没恢复好怎么办 cf我是新手不知道怎么报点怎么办 挑战人物已经有了又刷到怎么办 小米手机账户验证码隐藏了怎么办? 苹果手机绑定的邮箱密码忘了怎么办 魔域手机版不要的装备怎么办 魔域永恒多了的幻兽装备怎么办 魔域怀旧版70星以后宝宝怎么办 天猫确认收货后不寄发票怎么办 足球运动员踢了一半想撒尿了怎么办 17个月宝宝0型腿怎么办 走的路多了腿疼怎么办 如果新兵老被老兵打怎么办求求个位 做古董拍卖诈骗被警察抓了怎么办 武汉个人社保怎么办停转到海南来 狗狗车祸前脚软组织受伤了怎么办 6岁儿童夜里盗汗惊战发抖怎么办 一个月大的小狗尾巴掉毛怎么办 口袋妖怪用修改器被ban了怎么办 联币金融提现不到账怎么办 秘密花园的手抄报怎么办?五年级 雷蛇鼠标不亮了怎么办呢 汽车后备箱的垫子好臭怎么办 摩托尾箱内衬味道太重怎么办 买房子把办贷款的单据丢了怎么办 鞋盒破损卖家拒绝退货怎么办 顺丰快递退回发件人签收失败怎么办