hdu 6096 String(AC自动机)
来源:互联网 发布:昆仑墟麒麟臂升阶数据 编辑:程序博客网 时间:2024/05/22 05:13
转换还是比较巧妙的。
因为要求前缀后缀都包含的个数,所以可以把字符串a转换成a#a这样一个字符串,比如abca就转换成abca#abca
然后对于一组前缀a后缀b转换成b#a,比如ab ca,就是ca#ab,
然后对前缀后缀的串建立AC自动机,让主串去匹配,如上述例子,ca#ab满足为abca#abca的一个子串,也就是abca满足这个前缀后缀,所以问题,就转换成了典型的ac自动机匹配问题。
加个#的原因是为了只让后缀#前缀这种串能在AC自动机匹配到。
然后求答案的时候,需要对连接到自己的fail的位置累加一下,含义想一下就明白了。
代码:
#include <bits/stdc++.h>using namespace std;const int maxn=1e6+5+1e5;char str[maxn];char *s[maxn];int d[maxn], pos[maxn], ans[maxn], st[maxn], len[maxn];char s1[maxn], s2[maxn];struct acho{ int nex[maxn+10][29], cnt[maxn+10], fail[maxn+10], match[maxn+10], nl[maxn+10]; int L, root; int newnode() { for(int i=0; i<27; i++)nex[L][i]=-1; cnt[L++]=0; fail[L-1]=0; return L-1; } void init() { L=0; root=newnode(); } int insert(char *a) { int now=root, i; for(i=0; a[i]; i++) { if(nex[now][a[i]-'a']==-1) { nex[now][a[i]-'a']=newnode(); nl[L-1]=i+1; } now=nex[now][a[i]-'a']; } cnt[now]=1; return now; } queue<int>que; void build() { while(que.empty()==0)que.pop(); int now=root; for(int i=0; i<27; i++) { if(nex[now][i]==-1)nex[now][i]=root; else { fail[nex[now][i]]=root; que.push(nex[now][i]); } } while(que.empty()==0) { now=que.front(); que.pop(); for(int i=0; i<27; i++) { if(nex[now][i]!=-1) { que.push(nex[now][i]); fail[nex[now][i]]=nex[fail[now]][i]; match[nex[now][i]]=cnt[nex[now][i]]?nex[now][i]:match[nex[fail[now]][i]]; } else { nex[now][i]=nex[fail[now]][i]; } } } return; } void search(char *a, int len) { int i, now=root;// printf("%s\n", a); for(i=0; a[i]; i++) { now=nex[now][a[i]-'a']; while(nl[now]>len) { now=fail[now]; } ans[match[now]]++;// printf("%c %d\n", a[i], now); } } void cal() { memset(d, 0, sizeof(int)*(L+1)); int j, k=0, i; for(i=0; i<L; i++)d[fail[i]]++; for(i=0; i<L; i++)if(!d[i])st[k++]=i; for(i=0; i<k; i++) { j=fail[st[i]]; ans[j]+=ans[st[i]]; if(!(--d[j]))st[k++]=j; } return; }}acho;int main(){ int t, i, j, n, q; cin>>t; while(t--) { acho.init(); scanf("%d%d", &n, &q); j=0; for(i=0; i<n; i++) { s[i]=str+j; scanf("%s", s[i]); len[i]=strlen(s[i])+1; j+=len[i]; strcpy(str+j, s[i]); str[j-1]='z'+1; j+=len[i]; } for(i=0; i<q; i++) { scanf("%s%s", s1+1, s2); s1[0]='z'+1; strcat(s2, s1); pos[i]=acho.insert(s2);// printf("%d ", pos[i]); }// printf("\n"); acho.build();// for(i=0; i<acho.L; i++)printf("%d %d\n", i, acho.match[i]); for(i=0; i<n; i++) { acho.search(s[i], len[i]); } acho.cal(); for(i=0; i<q; i++)printf("%d\n", ans[pos[i]]); for(i=0; i<=acho.L; i++) { ans[i]=0; acho.match[i]=0; } } return 0;}
阅读全文
0 0
- HDU 6096 (String) AC自动机
- hdu 6096 String(AC自动机)
- HDU 6096 String(AC自动机)
- HDU 6096 String AC自动机(多种解法)
- hdoj-6096String(AC自动机)
- hdu6096 String AC自动机
- hdu6096 String【AC自动机】
- 2017多校联合第六场String/hdu 6096 (tire tree/ac自动机)
- HDU--3407[String-Matching Automata] AC自动机或kmp
- hdu 6086 Rikka with String ac自动机+dp
- Hdu-6086 Rikka with String(AC自动机+DP)
- hdu 6086 -- Rikka with String(AC自动机 + 状压DP)
- HDU 6096:妙用AC自动机(666)
- AC自动机 hdu 2222
- HDU 2222(AC 自动机)
- hdu 2222 AC自动机
- hdu 3065(AC自动机)
- HDU 2222 AC自动机
- HashMap的数据结构
- 金融数据的尖峰厚尾
- 安卓工作室 android studio 汉化后,报错。 设置界面打不开。Can't find resource for bundle java.util.PropertyResourceBundle
- HexUtil工具类
- idea 开发插件。
- hdu 6096 String(AC自动机)
- 你也可以找到好工作(三)大结局
- android studio java工程 报错
- centos7搭建nexus maven私服
- HDU-6105 Gameia
- 关于HttpServletRequest对象
- android monitor 汉化 ddms
- redis常见的数据类型
- 关于MongoDB的多条件查询问题