hdu 2222 Keywords Search(AC自动机)
2015-09-16 14:50
429 查看
题意:
给你很多个单词,然后给你一篇文章,问给出的单词在文章中出现的次数。解析:
直接套用AC自动机的模板。注意:
每个单词在目标串中出现的话,只能记为一次。mymy codecode
[code]#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int maxnode = (int)1e6 + 10; const int sigma_size = 26; struct AC { int ch[maxnode][sigma_size]; int fail[maxnode]; int last[maxnode]; int val[maxnode]; int sz; int ans; void clear() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); } inline int idx(char c) { return c - 'a'; } void insert(char *s) { int u = 0, n = strlen(s); for(int i = 0; i < n; i++) { int c = idx(s[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u]++; } int find(char* tar) { int n = strlen(tar); int v = 0; ans = 0; for(int i = 0; i < n; i++) { int c = idx(tar[i]); while(v && !ch[v][c]) v = fail[v]; v = ch[v][c]; if(val[v]) print(v); else if(last[v]) print(last[v]); } return ans; } void print(int j) { while(j) { ans += val[j]; //找到的话,将所有的val[j]都加进来 val[j] = 0; //然后将val[j]清空,之后就算有相同的单词也可以不用计算。 j = last[j]; } } int getFail() { //构造失配指针 queue<int> que; //初始化队列 //root的子节点的失配指针都指向root。 for(int c = 0; c < sigma_size; c++) { int u = ch[0][c]; if(u) { fail[u] = 0; que.push(u); last[u] = 0; } } //节点(字符为x)的失败指针指向:从x节点的父节点的fail节点回溯直到找到某节点的子节点也是字符x,没有找到就指向root。 //按照bfs顺序计算失配函数 while(!que.empty()) { int r = que.front(); que.pop(); //取出队首,遍历当前的子节点 for(int c = 0; c < sigma_size; c++) { int u = ch[r][c]; //当前的子节点 if(!u) continue; //且子节点不能为空 que.push(u); //将不为空的子节点存入队列 int v = fail[r]; //r = x 节点的父节点的fail节点 //从x节点的父节点的fail节点回溯,直到找到某节点的子节点也是字符x //ch[v][c] == 0表示其子节点不是x,可以继续向上找; //v != 0,fail[v]存在,表示还能向上找 while(v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; //找到某节点的子节点也是字符x,将u的失配指针指向最近的某节点的子节点也是字符x last[u] = val[fail[u]] ? fail[u] : last[fail[u]]; } } } } ac; const int MAXN = (int)1e4 + 10; char key[MAXN][55]; char tar[maxnode]; int n; int main() { int T; scanf("%d", &T); while(T--) { ac.clear(); scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s", key[i]); ac.insert(key[i]); } ac.getFail(); scanf("%s", tar); printf("%d\n", ac.find(tar)); } return 0; }
相关文章推荐
- 淘宝如何跨域获取Cookie分析
- (整理篇三)Android知识图谱
- [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段
- iOS申请真机调试证书 图文详解
- Cisco.PIX防火墙配置
- 用JS scrollHeight方法实现textarea输入高度自适应的方法
- 调试笔记
- 关于FD_CLOEXEC的一个故事 http://leave001.blog.163.com/blog/static/162691293201251810343121/
- Unity物理关节:关节简介(可配置关节)
- 关于 No operations allowed after connection closed.错误
- CGRectInset的使用
- Look and Say-3438
- [Elasticsearch] 多字段搜索 (四) - 跨字段实体搜索
- [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询
- 【Leetcode】Path Sum II
- THINKPHP 错误:Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'
- poj2689 Prime Distance
- DMZ基础及应用
- JS实现光滑展开合拢的菜单效果代码
- Cisco交换机接口模式精解