BZOJ2780: [Spoj]8093 Sevenk Love Oimaster(广义后缀自动机,Parent树,Dfs序)

Description

Oimaster and sevenk love each other.
But recently,sevenk heard that a girl named ChuYuXun was dating with oimaster.As a woman's nature, s
evenk felt angry and began to check oimaster's online talk with ChuYuXun.    Oimaster talked with Ch
uYuXun n times, and each online talk actually is a string.Sevenk asks q questions like this,    "how
 many strings in oimaster's online talk contain this string as their substrings?"
有n个大串和m个询问,每次给出一个字符串s询问在多少个大串中出现过

Input

There are two integers in the first line, 
the number of strings n and the number of questions q.
And n lines follow, each of them is a string describing oimaster's online talk. 
And q lines follow, each of them is a question.
n<=10000, q<=60000 
the total length of n strings<=100000, 
the total length of q question strings<=360000

Output

For each question, output the answer in one line.

Sample Input

3 3
abcabcabc
aaa
aafe
abc
a
ca

Sample Output

1
3
1

解题思路:

利用Parent树的子节点都是父节点母串的性质,在大串的每个实节点打上标记,然后构建出这颗Parent树。

那么我们的问题就变成了在一个Fail节点子树内不同颜色个数。

像不像HH的项链?

把Dfs序构建出来,离线树状数组就好了。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 const int N=200000;
  5 const int M=1000000;
  6 struct sant{
  7     int tranc[26];
  8     int len;
  9     int pre;
 10 }s[N];
 11 struct pnt{
 12     int hd;
 13     int col;
 14     int ind;
 15     int oud;
 16 }p[N];
 17 struct ent{
 18     int twd;
 19     int lst;
 20 }e[N];
 21 struct qust{
 22     int l,r;
 23     int ans;
 24     int no;
 25 }q[N];
 26 int siz;
 27 int fin;
 28 int n,Q;
 29 int cnt;
 30 int dfn;
 31 char tmp[N];
 32 int line[N];
 33 int lst[N];
 34 int phr[N];
 35 int col[N];
 36 void Insert(int c,int whic)
 37 {
 38     int nwp,nwq,lsp,lsq;
 39     nwp=++siz;
 40     p[nwp].col=whic;
 41     s[nwp].len=s[fin].len+1;
 42     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
 43         s[lsp].tranc[c]=nwp;
 44     if(!lsp)
 45         s[nwp].pre=1;
 46     else{
 47         lsq=s[lsp].tranc[c];
 48         if(s[lsq].len==s[lsp].len+1)
 49             s[nwp].pre=lsq;
 50         else{
 51             nwq=++siz;
 52             s[nwq]=s[lsq];
 53             s[nwq].len=s[lsp].len+1;
 54             s[nwp].pre=s[lsq].pre=nwq;
 55             while(s[lsp].tranc[c]==lsq)
 56             {
 57                 s[lsp].tranc[c]=nwq;
 58                 lsp=s[lsp].pre;
 59             }
 60         }
 61     }
 62     fin=nwp;
 63     return ;
 64 }
 65 void ade(int f,int t)
 66 {
 67     cnt++;
 68     e[cnt].twd=t;
 69     e[cnt].lst=p[f].hd;
 70     p[f].hd=cnt;
 71     return ;
 72 }
 73 void Dfs(int x)
 74 {
 75     p[x].ind=++dfn;
 76     phr[dfn]=x;
 77     col[dfn]=p[x].col;
 78     for(int i=p[x].hd;i;i=e[i].lst)
 79     {
 80         int to=e[i].twd;
 81         Dfs(to);
 82     }
 83     p[x].oud=dfn;
 84     return ;
 85 }
 86 bool cmp(qust x,qust y)
 87 {
 88     return x.r<y.r;
 89 }
 90 bool cmq(qust x,qust y)
 91 {
 92     return x.no<y.no;
 93 }
 94 int lowbit(int x)
 95 {
 96     return x&(-x);
 97 }
 98 void update(int pos,int x)
 99 {
100     while(pos&&pos<=siz)
101     {
102         line[pos]+=x;
103         pos+=lowbit(pos);
104     }
105     return ;
106 }
107 int query(int pos)
108 {
109     int ans=0;
110     while(pos)
111     {
112         ans+=line[pos];
113         pos-=lowbit(pos);
114     }
115     return ans;
116 }
117 int main()
118 {
119     fin=++siz;
120     scanf("%d%d",&n,&Q);
121     for(int i=1;i<=n;i++)
122     {
123         scanf("%s",tmp+1);
124         fin=1;
125         int len=strlen(tmp+1);
126         for(int j=1;j<=len;j++)
127             Insert(tmp[j]-'a',i);
128     }
129     for(int i=2;i<=siz;i++)
130         ade(s[i].pre,i);
131     Dfs(1);
132     
133     for(int i=1;i<=Q;i++)
134     {
135         scanf("%s",tmp+1);
136         int root=1;
137         int len=strlen(tmp+1);
138         for(int j=1;j<=len;j++)
139             root=s[root].tranc[tmp[j]-'a'];
140         q[i].no=i;
141         if(!root)
142             continue;
143         q[i].l=p[root].ind;
144         q[i].r=p[root].oud;
145     }
146     std::sort(q+1,q+Q+1,cmp);
147     int rr=1;
148     for(int i=1;i<=Q;i++)
149     {
150         while(rr<=q[i].r)
151         {
152             if(!col[rr])
153             {
154                 rr++;
155                 continue;
156             }
157             if(lst[col[rr]])
158                 update(lst[col[rr]],-1);
159             update(rr,1);
160             lst[col[rr]]=rr;
161             rr++;
162         }
163         rr--;
164         if(!q[i].l)
165             continue;
166         q[i].ans=query(q[i].r)-query(q[i].l-1);
167     }
168     std::sort(q+1,q+Q+1,cmq);
169     for(int i=1;i<=Q;i++)
170         printf("%d\n",q[i].ans);
171     return 0;
172 }

 

posted @ 2018-11-30 19:00  Unstoppable728  阅读(303)  评论(0编辑  收藏  举报