都快忘了在这类题的经典做法了……

将字符串一个个的插入字典树,在字典树维护好有该前缀串s的最大编号字符串j,我们记作j控制了前缀串s

对于当前的第i个字符串,维护此时有当前每个字符串控制了多少个前缀串,用一个线段树维护。

由于询问是在线的,所以用主席树来维护。于是对一个询问(l,r),在第r个线段树求一下区间(l,r)的和即为答案。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 struct node{int l,r,s;} tree[200010*20];
 8 int go[100010][26],h[100010],be[100010];
 9 char s[100010];
10 int m,t,n,q;
11 
12 int build(int l,int r)
13 {
14   ++t; tree[t].l=tree[t].r=tree[t].s=0;
15   if (l==r) return t;
16   else {
17       int cur=t,m=(l+r)>>1;
18       tree[cur].l=build(l,m);
19       tree[cur].r=build(m+1,r);
20       return cur;
21   }
22 }
23 
24 int work(int l,int r,int last,int x,int w)
25 {
26   ++t; tree[t]=tree[last];
27   if (l==r) {tree[t].s+=w; return t;}
28   else {
29       int cur=t,m=(l+r)>>1;
30       if (x<=m) tree[cur].l=work(l,m,tree[last].l,x,w);
31       else tree[cur].r=work(m+1,r,tree[last].r,x,w);
32       tree[cur].s=tree[tree[cur].l].s+tree[tree[cur].r].s;
33       return cur;
34   }
35 }
36 
37 int ask(int l,int r,int p,int x,int y)
38 {
39   if (x<=l&&y>=r) return tree[p].s;
40   else {
41       int m=(l+r)>>1,s=0;
42       if (x<=m) s+=ask(l,m,tree[p].l,x,y);
43       if (y>m) s+=ask(m+1,r,tree[p].r,x,y);
44       return s;
45   }
46 }
47 
48 int main()
49 {
50   while (scanf("%d",&n)!=EOF)
51   {
52     t=m=0;
53     h[0]=build(1,n);
54     memset(go[0],0,sizeof(go[0]));
55     for (int i=1; i<=n; i++)
56     {
57       scanf("%s",s+1);
58       int k=0,l=strlen(s+1);
59       h[i]=h[i-1];
60       for (int j=1; j<=l; j++)
61       {
62         int c=s[j]-'a';
63         if (!go[k][c]) {go[k][c]=++m; memset(go[m],0,sizeof(go[m])); be[m]=0;}
64         k=go[k][c];
65         if (be[k]) h[i]=work(1,n,h[i],be[k],-1);
66         be[k]=i;
67       }
68       h[i]=work(1,n,h[i],i,l);
69     }
70     scanf("%d",&q);
71     int z=0;
72     for (int i=1; i<=q; i++)
73     {
74       int l,r;
75       scanf("%d%d",&l,&r);
76       l=(z+l)%n+1; r=(z+r)%n+1;
77       if (l>r) swap(l,r);
78       z=ask(1,n,h[r],l,r);
79       printf("%d\n",z);
80     }
81   }
82   return 0;
83 }
View Code

 

posted on 2016-08-25 14:48  acphile  阅读(159)  评论(0编辑  收藏  举报