LA4670 AC自动机模版题
来源:互联网 发布:童装淘宝店铺简介 编辑:程序博客网 时间:2024/05/22 08:23
这里有个大神的博客:http://www.cnblogs.com/yefeng1627/archive/2013/05/23/3094566.html
题意:给你一些模式串和一个文本串,求在文本串中出现次数最多的模式串,输出次数和这些模式串。
文本串很长,模式串数量多但长度短,适用于AC自动机。
第一写AC自动机,基本照着敲的,不过稍微懂了些,希望早点掌握啦。
这题直接先建一个AC自动机,把串都编号,用map来防重复,在AC自动机里用一个cnt数组记录所有串的编号的出现次数,最后遍历所有串的边号,找出最多的次数,然后在遍历所有的字符串,找出串编号出现次数等于最大值的串。
代码:
#include<iostream>#include<cstdio>#include<vector>#include<string>#include<map>#include<queue>#include<cmath>#include<algorithm>#include<cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 10005#define INF 0xfffffff#define mem(a,b) memset(a,b,sizeof(a))#define FOR(i,s,t) for(int i=s;i<=t;i++)#define ull unsigned long long#define ll long long#define N 20000#define M 1000006using namespace std;struct AC{ int ch[N][26],f[N],last[N]; int val[N],cnt[N]; int top; void init()//基本都得置0 { top=0; memset(ch,0,sizeof(ch)); memset(f,0,sizeof(f)); memset(last,0,sizeof(last)); memset(val,0,sizeof(val)); memset(cnt,0,sizeof(cnt)); } int NewNode() { int x=++top; return x; } void insert(char *s,int num)//传参串的编号,类似trie的构建 { int l=strlen(s); int p=0; for(int i=0; i<l; i++) { int c=s[i]-'a'; if(ch[p][c]==0) { ch[p][c]=NewNode(); } p=ch[p][c]; } val[p]=num; } void getfail()//求每个结点的f数组和last数组,分别表示失配指针和失配的模式串指针 { queue<int> q; for(int c=0; c<26; c++)//初始化所有只有一个字符的节点的失配指针都指向树根 { int u=ch[0][c]; if(u) { f[u]=0; last[u]=0; q.push(u); } } while(!q.empty()) { int r=q.front(); q.pop(); for(int c=0; c<26; c++) { int u=ch[r][c]; if(!u)//如果r没有c这个子孙,那么就连到与r的失配指针指向的节点的c子孙 { ch[r][c]=ch[f[r]][c]; continue; } q.push(u);//如果该节点存在,更新f和last数组 int v=f[r]; while(v&&!ch[v][c]) v=f[v];//更新f f[u]=ch[v][c]; last[u]=val[f[u]]?f[u]:last[f[u]];//更新last } } } void find(char *s) { int n=strlen(s); int p=0; for(int i=0; i<n; i++) { int c=s[i]-'a'; p=ch[p][c];//这里直接匹配,可能匹配成功,也可能失败 if(val[p]) count(p);//如果匹配成功,并且有这个串,就计数 else if(last[p])//如果改点不是模式串,那就看他的失配指针 { count(last[p]); } } } void count(int x) { if(x)//如果改点是模式串就计数,并且把有相同后记的所有节点递归计数 { cnt[val[x]]++; if(last[x]) { count(last[x]); } } }} ac;map<char*,int> mp;char text[M];char str[155][77];int main(){ int n; while(scanf("%d",&n)==1) { if(!n) break; mp.clear(); ac.init(); int tot=0; for(int i=1; i<=n; i++) { scanf("%s",str[i]); if(mp.count(str[i])==0) mp[str[i]]=++tot; ac.insert(str[i],mp[str[i]]); } ac.getfail(); scanf("%s",text); ac.find(text); int k=0; for(int i=1; i<=tot; i++) { k=max(k,ac.cnt[i]); } printf("%d\n",k); for(int i=1; i<=n; i++) { if(ac.cnt[mp[str[i]]]==k) { printf("%s\n",str[i]); } } } return 0;}
- LA4670 AC自动机模版题
- AC自动机 LA4670
- AC自动机模板 LA4670
- LA4670 AC自动机
- LA4670 Dominating Patterns[AC自动机]
- LA4670 Dominating Patterns(AC自动机)
- HDOJ2222 AC自动机模版题
- HDU 2222 AC自动机模版题
- hdu 2896 AC自动机模版题
- hdu 3065 AC自动机模版题
- HDU 2222 AC自动机模版题
- HDU 2896 AC自动机模版题
- HDU 3065 AC自动机模版题
- hdu2222 ac自动机模版
- AC自动机模版
- AC自动机模版
- AC自动机模版
- AC自动机模版
- 像C++一样写JavaScript
- 每位开发人员都应铭记的10句编程谚语
- js常用函数
- 动态变量vs常量 动态存储vs静态存储
- Running your own CloudFoundry based on your IaaS. Part 1
- LA4670 AC自动机模版题
- Running your own CloudFoundry based on your IaaS. Part 2
- 程序员的十层楼,看看你在哪一层
- HtmlUnit实现ajax网络爬虫
- 由一个论坛帖子, 解决udp 服务器无法返回数据给第一个客户端的问题
- bluez plugins
- asd
- 强大的sublim-text2/3 注册方法 (for Windows x64)
- 和为指定值的连续序列