zoj 3228 Searching the String (ac自动机)
来源:互联网 发布:附近淘宝店 编辑:程序博客网 时间:2024/05/22 12:26
题意:
给出一个目标串,已经一些单词,每个单词有一个限制,0表示找到目标串中包含重叠部分出现的次数,1相反。
可以有多个相同的单词。
题解:
如果直接kmp 复杂度O(n^2)超时。那么可以考虑ac自动,将单词存入字典树整体匹配。最蛋疼的是多个单词重复是允许的。那么我们要存对应编号的单词在字典树中的位置这样输出处理都方便只要处理字典树上的对应节点即可。对于不可以重叠的单词的计数,添加一个数组标记上次出现的位置,然后通过判断是否重叠来累加。
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))typedef long long ll;const int oo=0x3f3f3f3f;const ll OO=1LL<<61;const ll MOD=20090717;const int maxn=100005;const int SIZE=maxn*6;const int alph=26;char str[maxn],ss[10];int ans[SIZE][2];int last[SIZE];int pos[maxn],type[maxn];struct AC{ int next[SIZE][alph],fail[SIZE],length[SIZE]; int root,cnt; void Init() { cnt=0; root=newNode(); } int newNode() { for(int i=0;i<alph;i++) next[cnt][i]=-1; length[cnt++]=0; return cnt-1; } void Insert(char buff[],int id) { int now=root; int len=strlen(buff); for(int i=0,k;i<len;i++) { k=buff[i]-'a'; if(next[now][k]==-1) { next[now][k]=newNode(); length[next[now][k]]=i+1; } now=next[now][k]; } pos[id]=now; } void build() { queue<int>Q; fail[root]=root; int now=root; for(int i=0;i<alph;i++) { if(next[now][i]==-1) next[now][i]=root; else { fail[next[now][i]]=root; Q.push(next[now][i]); } } while(!Q.empty()) { now=Q.front(); Q.pop(); for(int i=0;i<alph;i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } } void Search(char buff[]) { int len=strlen(buff); int now=root; memset(ans,0,sizeof ans); memset(last,-1,sizeof last); for(int i=0;i<len;i++) { int k=buff[i]-'a'; now=next[now][k]; int temp=now; while(temp!=root) { ans[temp][0]++; if(i-last[temp]>=length[temp]) { ans[temp][1]++; last[temp]=i; } temp=fail[temp]; } } }};AC ac;int main(){ int n,cas=1,f; while(scanf("%s",&str)!=EOF) { scanf("%d",&n); ac.Init(); for(int i=1;i<=n;i++) { scanf("%d %s",&type[i],ss); ac.Insert(ss,i); } ac.build(); ac.Search(str); printf("Case %d\n",cas++); for(int i=1;i<=n;i++) printf("%d\n",ans[pos[i]][type[i]]); puts(""); } return 0;}/***/
0 0
- 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 3228 Searching the String 【AC自动机】
- ZOJ 3228 Searching the String(AC自动机)
- [AC自动机] zoj Searching the String
- ZOJ Problem Set - 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 3328 Searching the String (AC自动机)
- ZOJ 3228Searching the String AC自动机的不重复匹配
- 一个简单的可以实现分页的SqlHelper类
- Thinking in Java学习笔记
- CF 518C(Anya and Smartphone-映射)
- 黑马程序员--String类的知识
- Linux增强系统安全性:防止单用户模式(single)修改密码
- zoj 3228 Searching the String (ac自动机)
- POJ 3321 Apple Tree(树状数组)
- NSUserDefaults
- ecshop Ajax.call的使用
- 叉乘计算多边形面积:poj 1654 Area
- ORACLE 获取同期数据的两种方法
- 传球游戏
- SQL_Oracle 表中ID字段的自动递增
- HDOJ 1283 最简单的计算机(水)