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的位置累加一下,含义想一下就明白了。


代码:

[cpp] view plain copy
  1. #include <bits/stdc++.h>  
  2.   
  3. using namespace std;  
  4. const int maxn=1e6+5+1e5;  
  5. char str[maxn];  
  6. char *s[maxn];  
  7. int d[maxn], pos[maxn], ans[maxn], st[maxn], len[maxn];  
  8. char s1[maxn], s2[maxn];  
  9. struct acho  
  10. {  
  11.     int nex[maxn+10][29], cnt[maxn+10], fail[maxn+10], match[maxn+10], nl[maxn+10];  
  12.     int L, root;  
  13.     int  newnode()  
  14.     {  
  15.         for(int i=0; i<27; i++)nex[L][i]=-1;  
  16.         cnt[L++]=0;  
  17.         fail[L-1]=0;  
  18.         return L-1;  
  19.     }  
  20.     void init()  
  21.     {  
  22.         L=0;  
  23.         root=newnode();  
  24.     }  
  25.     int insert(char *a)  
  26.     {  
  27.         int now=root, i;  
  28.         for(i=0; a[i]; i++)  
  29.         {  
  30.             if(nex[now][a[i]-'a']==-1)  
  31.             {  
  32.                 nex[now][a[i]-'a']=newnode();  
  33.                 nl[L-1]=i+1;  
  34.             }  
  35.             now=nex[now][a[i]-'a'];  
  36.         }  
  37.         cnt[now]=1;  
  38.         return now;  
  39.     }  
  40.     queue<int>que;  
  41.     void build()  
  42.     {  
  43.         while(que.empty()==0)que.pop();  
  44.         int now=root;  
  45.         for(int i=0; i<27; i++)  
  46.         {  
  47.             if(nex[now][i]==-1)nex[now][i]=root;  
  48.             else  
  49.             {  
  50.                 fail[nex[now][i]]=root;  
  51.                 que.push(nex[now][i]);  
  52.             }  
  53.         }  
  54.         while(que.empty()==0)  
  55.         {  
  56.             now=que.front();  
  57.             que.pop();  
  58.             for(int i=0; i<27; i++)  
  59.             {  
  60.                 if(nex[now][i]!=-1)  
  61.                 {  
  62.                     que.push(nex[now][i]);  
  63.                     fail[nex[now][i]]=nex[fail[now]][i];  
  64.                     match[nex[now][i]]=cnt[nex[now][i]]?nex[now][i]:match[nex[fail[now]][i]];  
  65.                 }  
  66.                 else  
  67.                 {  
  68.                     nex[now][i]=nex[fail[now]][i];  
  69.                 }  
  70.             }  
  71.         }  
  72.         return;  
  73.     }  
  74.   
  75.     void search(char *a, int len)  
  76.     {  
  77.         int i, now=root;  
  78. //        printf("%s\n", a);  
  79.         for(i=0; a[i]; i++)  
  80.         {  
  81.             now=nex[now][a[i]-'a'];  
  82.             while(nl[now]>len)  
  83.             {  
  84.                 now=fail[now];  
  85.             }  
  86.             ans[match[now]]++;  
  87. //            printf("%c %d\n", a[i], now);  
  88.         }  
  89.     }  
  90.   
  91.     void cal()  
  92.     {  
  93.         memset(d, 0, sizeof(int)*(L+1));  
  94.         int j, k=0, i;  
  95.         for(i=0; i<L; i++)d[fail[i]]++;  
  96.         for(i=0; i<L; i++)if(!d[i])st[k++]=i;  
  97.         for(i=0; i<k; i++)  
  98.         {  
  99.             j=fail[st[i]];  
  100.             ans[j]+=ans[st[i]];  
  101.             if(!(--d[j]))st[k++]=j;  
  102.         }  
  103.         return;  
  104.     }  
  105. }acho;  
  106. int main()  
  107. {  
  108.     int t, i, j, n, q;  
  109.     cin>>t;  
  110.     while(t--)  
  111.     {  
  112.         acho.init();  
  113.         scanf("%d%d", &n, &q);  
  114.         j=0;  
  115.         for(i=0; i<n; i++)  
  116.         {  
  117.             s[i]=str+j;  
  118.             scanf("%s", s[i]);  
  119.             len[i]=strlen(s[i])+1;  
  120.             j+=len[i];  
  121.             strcpy(str+j, s[i]);  
  122.             str[j-1]='z'+1;  
  123.             j+=len[i];  
  124.         }  
  125.         for(i=0; i<q; i++)  
  126.         {  
  127.             scanf("%s%s", s1+1, s2);  
  128.             s1[0]='z'+1;  
  129.             strcat(s2, s1);  
  130.             pos[i]=acho.insert(s2);  
  131. //            printf("%d ", pos[i]);  
  132.         }  
  133. //        printf("\n");  
  134.         acho.build();  
  135. //        for(i=0; i<acho.L; i++)printf("%d %d\n", i, acho.match[i]);  
  136.         for(i=0; i<n; i++)  
  137.         {  
  138.             acho.search(s[i], len[i]);  
  139.         }  
  140.   
  141.         acho.cal();  
  142.         for(i=0; i<q; i++)printf("%d\n", ans[pos[i]]);  
  143.         for(i=0; i<=acho.L; i++)  
  144.         {  
  145.             ans[i]=0;  
  146.             acho.match[i]=0;  
  147.         }  
  148.     }  
  149.     return 0;  
  150. }  
原创粉丝点击