HDU 2222 Keywords Search (AC自动机)
来源:互联网 发布:迈视高清网络摄像机 编辑:程序博客网 时间:2024/06/06 02:02
http://acm.hdu.edu.cn/showproblem.php?pid=2222
题意:给你一些单词,然后给你一段很长的话,问你话里有多少个之前给你的那些单词(重复的只算一次)。
方法:AC自动机,即把trie树和kmp的失效匹配相结合。
AC代码如下:
#include <iostream>#include <cstdio>#include <string.h>#include <queue>using namespace std;#define maxnode 500100#define sigma 26 struct ac_automation{ int ch[maxnode][sigma]; // maxnode 一般设置为 模式串数量*模式串长度 //char数组里存的都是位置信息,甚至包含了一些失效指针的信息。 bool val[maxnode]; int cnt[maxnode]; // count 数量 int last[maxnode]; // 储存着最后在查询时需要向上层回溯的地址。 int f[maxnode]; // fail指针 储存着指向的地址 int sz; // the num of the trie int ans; // answer void clear(){ // 初始化 sz = 1; ans = 0; memset(ch[0],0,sizeof(ch[0])); memset(val,0,sizeof(val)); memset(cnt,0,sizeof(cnt)); } int idx(char c){ return c - 'a'; } void insert(char s[]/*,int v*/){ // 构建trie树 int u = 0; for(int i = 0; s[i];i++){ int c = idx( s[i] ); if(!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); ch[u][c] = sz++; } u = ch[u][c]; } cnt[u]++; val[u] = 1; //v; } void build(){ // 构建失效指针 //注意:构建失效匹配的时候是按照bfs的思想来的 //就是一层一层的,即:下层的f[]和last[]是根据上层的数据来的 f[0] = 0; queue<int> q; for(int i = 0;i < sigma;i++){ if(ch[0][i]){ f[ch[0][i]] = 0; // 第一层的节点的fail指针应该指向root(0) q.push(ch[0][i]);// 放进队列 last[ch[0][i]] = 0;//上一层绝对是root(0) } } while(!q.empty()){ int now = q.front(); q.pop(); for(int i = 0;i < sigma ;i++){ int son = ch[now][i]; if(!son){ ch[now][i] = ch[f[now]][i]; // 提前将失效后指向此位置的的失效指针指向它应该指向的位置。 //因为这里找不到应有的字母,所以它应该等于自己的失效指针所指向的位置。 continue; } q.push(son); f[son] = ch[f[now]][i]; last[son] = val[f[son]] ? f[son] : last[f[son]]; /* 如果此处的fail指针指向的位置是之前插入单词的结尾, 那么son节点的上一层(last)就为它的失效指针, 否则去找他的失效指针的的上一层(此处一定有一个有意义的值,因为上层已经确定)*/ } } } void find(char *s){ int u = 0; for(int i = 0;s[i];i++){ int c = idx(s[i]); u = ch[u][c]; if(val[u]){ print(u); } else{ print(last[u]); } } } void print(int u){ if(u){ ans += cnt[u]; cnt[u] = 0; // 因为只是找出有多少个匹配的,计入ans后需要清零,避免重复记录。 print(last[u]); } }}ac;char s[60];char text[1000100];int main(){ int ncase; cin>>ncase; while(ncase--){ int n; cin>>n; ac.clear(); for(int i = 0;i < n; i++){ scanf("%s",s); ac.insert(s); } ac.build(); scanf("%s",text); ac.find(text); printf("%d\n",ac.ans); } return 0;}
1 0
- hdU 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- HDU 2222 Keywords Search (AC自动机)
- hdu - 2222 - Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC 自动机)
- HDU 2222 - Keywords Search (AC自动机)
- HDU - 2222 Keywords Search (AC自动机)
- HDU - 2222 Keywords Search (AC自动机)
- HDU 2222 Keywords Search(AC自动机)
- HDU 2222 Keywords Search (AC自动机)
- HDU 2222 Keywords Search(AC自动机)
- hdu 2222 Keywords Search(AC自动机)
- HDU 2222 Keywords Search (AC自动机)
- HDU 2222Keywords Search (ac自动机)
- HDU 2222 Keywords Search(AC自动机)
- HDU-2222 Keywords Search(AC自动机)
- 重写比较器遇到错误参数异常的问题
- linux top命令中CPU 占用说明
- 数组中只出现一次的数字
- ProgressDialog简单用法,软件登录、注册时弹出Dialog
- Oil Deposits(DFS)
- HDU 2222 Keywords Search (AC自动机)
- C++11读书笔记—1(长期历史遗留问题,宏定义与类型)
- 函数柯里化
- HTMLCSS基础-选择符优先级
- HDU 3966 Aragorn's Story
- Android的四大组件之-Activity的状态和生命周期
- 设计模式-享元模式
- Unity-命令模式-UnDo
- webView头部加进度加载效果