hdu 6096
来源:互联网 发布:好的南方二本院校知乎 编辑:程序博客网 时间:2024/05/22 01:12
因为要求前缀后缀都包含的个数,所以可以把字符串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;
-
- for(i=0; a[i]; i++)
- {
- now=nex[now][a[i]-'a'];
- while(nl[now]>len)
- {
- now=fail[now];
- }
- ans[match[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);
-
- }
-
- acho.build();
-
- 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;
- }