ZOJ 3328 Searching the String (AC自动机)
来源:互联网 发布:淘宝网店转让有风险吗 编辑:程序博客网 时间:2024/05/16 07:48
题目大意
- 输入一个文本串和若干模板串。统计每个模板串在文本串中出现的次数。
- 模板串有0和1两种类型,0型在文本串中可以重叠,1型的不可以重叠。
分析
- 把所有模板串建成一个AC自动机
- 求出字典树上所有串以0型和1型在文本串种出现的次数,即cnt[i][j]表示根节点到节点i的串在文本串中以类型j出现的次数
- wordend[i]表示第i个模板串的在字典树的最后一个节点
- 所以 ans[i] = cnt[wordend[i]][type[i]]
- 注意:对于每个1型的串,只有当前位置到最后一次出现的位置的长度大于该串的长度时,才能对类型1计数+1
代码
/* cnt[i][j]表示根节点到节点i的串在文本串中以类型j出现的次数 * wordend[i]表示第i个模板串的在字典树的最后一个节点 * 所以 ans[i] = cnt[wordend[i]][type[i]] */#include <iostream>#include <string>#include <cstring>#include <queue>#include <cstdio>using namespace std;const int maxn = 600010;const int sigma_size = 26;int cnt[maxn][2] , wordend[maxn];struct AC { int ch[maxn][sigma_size]; int dep[maxn];//dep[i]表示节点i的深度 int sz; void Init() { sz = 1; dep[0] = 0; memset(ch[0],0 ,sizeof(ch[0])); } int idx(char c) {return c - 'a';} void Insert(string const &s , int v) { int cur = 0 , len = s.length(); for(int i = 0; i < len; i++) { int c = idx(s[i]); if(!ch[cur][c]) { memset(ch[sz] , 0 , sizeof(ch[sz])); dep[sz] = dep[cur] + 1; ch[cur][c] = sz++; } cur = ch[cur][c]; } wordend[v] = cur; } int f[maxn]; void getFail() { queue<int> Q; f[0] = 0; for(int i = 0; i < sigma_size; i++) { int u = ch[0][i]; if(u) {Q.push(u); f[u] = 0;}// last[u] = 0;} } while(!Q.empty()) { int cur = Q.front(); Q.pop(); for(int i = 0; i < sigma_size; i++) { int u = ch[cur][i]; if(!u) {ch[cur][i] = ch[f[cur]][i]; continue;} Q.push(u); int j = f[cur]; while(j && !ch[j][i]) j = f[j]; f[u] = ch[j][i]; } } } int last[maxn]; //last[i]表示节点i最后一次在s中出现的位置 void find(string const &s) { for(int i = 0; i < sz; i++) { cnt[i][0] = cnt[i][1] = 0; last[i] = -1; } int len = s.length() , cur = 0; for(int i = 0; i < len; i++) { int c = idx(s[i]); cur = ch[cur][c]; int tmp = cur; while(tmp) { cnt[tmp][0]++; /* 只有当前位置到最后一次出现的位置 * 的长度大于该串的长度时,才能对类型1计数+1 */ if(i - last[tmp] >= dep[tmp]) { cnt[tmp][1]++; last[tmp] = i; } tmp = f[tmp]; } } }};AC ac;const int maxs = 100010;char s[maxs] , str[maxs];int type[maxn];int main(){ int caseno = 1 , n; while(scanf("%s" , str) != EOF) { ac.Init(); cin >> n; for(int i = 1; i <= n; i++) { scanf("%d %s" , &type[i] , s); ac.Insert(s , i); } ac.getFail(); ac.find(str); //cout << "Case " << caseno++ << endl; printf("Case %d\n" , caseno++); for(int i = 1; i <= n; i++) printf("%d\n" , cnt[wordend[i]][type[i]]); printf("\n"); } return 0;}
0 0
- ZOJ 3328 Searching the String (AC自动机)
- zoj 3228 Searching the String【ac自动机】
- ZOJ 3228 Searching the String(AC自动机)
- ZOJ 3228 Searching the String(AC自动机)
- zoj -- 3228 Searching the String(AC自动机)
- ZOJ - 3228 Searching the String (AC自动机)
- [AC自动机] zoj Searching the String
- zoj 3228 Searching the String(AC自动机)
- ZOJ 3228 Searching the String AC自动机
- zoj 3228 Searching the String (ac自动机)
- zoj 3228 Searching the String 【AC自动机】
- ZOJ 3228 Searching the String(AC自动机)
- ZOJ 3228 Searching the String (AC自动机)
- ZOJ 3228 Searching the String(AC自动机)
- ZOJ 3228 Searching the String (AC自动机)
- ZOJ Problem Set - 3228 Searching the String AC自动机
- zoj 3228 Searching the String(AC自动机基本应用)
- ZOJ 题目3228 Searching the String(AC自动机,子川匹配个数)
- url 地址中的+(加号)问题
- HttpRouter项目中的问题
- 第一章作业
- C语言中枚举的使用
- #pragma 预处理指令详解
- ZOJ 3328 Searching the String (AC自动机)
- 黑马程序员——Swift学习笔记:声明与基本类型
- LightOJ _1138(二分查找)
- 流式套接字客户端/服务器编程 (迭代服务器+并发服务器)
- Swift 风格指南
- 让css 写的更规范
- 关于北京找工作的点滴记叙
- 返回的文件名不带扩展名
- Yii中的save方法