# *一道题20

$n \leq 200000$的字符串，$m \leq 200000$次操作：1，末尾加一个字符；2，末尾删一个字符；3，一个区间中，问某个串（新给的）出现次数。强制在线。

  1 //#include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 //#include<time.h>
5 //#include<complex>
6 //#include<set>
7 //#include<queue>
8 //#include<vector>
9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12
13 #define LL long long
15 {
16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
18 }
19
20 //Pay attention to '-' , LL and double of qread!!!!
21
22 int n,lq;
23 #define maxn 400011
24 char s[maxn],p[maxn];
25
26 int getnum(char c) {if (c>='a' && c<='z') return c-'a'; return c-'A'+26;}
27 int getch(int x) {if (x<26) return 'a'+x; return 'A'+x-26;}
28
29 int fail[maxn];
30 void solve1()
31 {
32     int op,x,y,last=0; char c;
33     while (lq--)
34     {
36         if (op==1)
37         {
38             while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
39             c=getch((getnum(c)+last)%52);
40             s[++n]=c;
41         }
42         else if (op==2) n--;
43         else
44         {
46             fail[1]=fail[2]=1;
47             int now=1;
48             while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
49             p[now]=getch((getnum(c)+last)%52);
50             while (((c=getchar())>='a' && c<='z') || (c>='A' && c<='Z'))
51             {
52                 p[++now]=getch((getnum(c)+last)%52);
53                 int j=fail[now];
54                 while (j>1 && p[j]!=p[now]) j=fail[j];
55                 fail[now+1]=p[j]==p[now]?j+1:1;
56             }
57             int ans=0;
58             for (int i=x,j=1;i<=y;i++)
59             {
60                 while (j>1 && p[j]!=s[i]) j=fail[j];
61                 if (p[j]==s[i]) j++;
62                 if (j>now) {ans++; j=fail[j];}
63             }
64             printf("%d\n",ans);
65             last=ans;
66         }
67     }
68 }
69
70 struct Edge{int to,next;};
71 struct SAM
72 {
73     struct Node{int ch[52],pos,Max,pre;}a[maxn];
74     int size,last;
75     int val[maxn],vvv[maxn];
76     SAM() {a[0].pre=-1; a[0].pos=a[0].Max=size=0; last=Time=0; le=2;}
77     void insert(int id,int pos)
78     {
79         int x=++size,y=last;
80         a[x].pos=pos; a[x].Max=n-pos+1; last=x; val[x]=pos;
81         for (;~y && !a[y].ch[id];y=a[y].pre) a[y].ch[id]=x;
82         if (!~y) a[x].pre=0;
83         else if (a[a[y].ch[id]].Max==a[y].Max+1) a[x].pre=a[y].ch[id];
84         else
85         {
86             int w=++size,z=a[y].ch[id]; a[w]=a[z]; a[w].Max=a[y].Max+1; a[w].pos=pos;
87             a[z].pre=a[x].pre=w;
88             for (;~y && a[y].ch[id]==z;y=a[y].pre) a[y].ch[id]=w;
89         }
90     }
91     Edge edge[maxn]; int first[maxn],le;
92     void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
93     int ll[maxn],rr[maxn],Time;
94     void predfs(int x)
95     {
96         ll[x]=++Time; vvv[Time]=val[x];
97         for (int i=first[x];i;i=edge[i].next)
98         {
99             Edge &e=edge[i];
100             predfs(e.to);
101         }
102         rr[x]=Time;
103     }
104     void maketree()
105     {
106         for (int i=1;i<=size;i++) in(a[i].pre,i);
107         Time=0; predfs(0);
108     }
109     bool go(int &x,int &p,char c)
110     {
111         Node &b=a[x];
112         if (p) {if (s[p]==c) p++; else return 0; if (p==b.pos+b.Max) p=0;}
113         else
114         {
115             bool flag=1;
116             for (int i=first[x];i;i=edge[i].next)
117             {
118                 Edge &e=edge[i];
119                 if (s[a[e.to].pos+a[x].Max]==c)
120                 {
121                     p=a[e.to].pos+a[x].Max+1; x=e.to;
122                     flag=0; break;
123                 }
124             }
125             if (flag) return 0;
126             if (p==a[x].pos+a[x].Max) p=0;
127         }
128         return 1;
129     }
130 }sa;
131
132 int root[maxn];
133 struct SMT
134 {
135     struct Node{int ls,rs,cnt;}a[maxn*20];
136     int size,n;
137     void clear(int N) {n=N; size=0;}
138     void insert(int &x,int y,int L,int R,int v)
139     {
140         x=++size; a[x].cnt=a[y].cnt+1;
141         if (L==R) return;
142         int mid=(L+R)>>1;
143         if (v<=mid) a[x].rs=a[y].rs,insert(a[x].ls,a[y].ls,L,mid,v);
144         else a[x].ls=a[y].ls,insert(a[x].rs,a[y].rs,mid+1,R,v);
145     }
146     void insert(int &x,int y,int v) {if (v) insert(x,y,1,n,v); else x=y;}
147     int ql,qr;
148     int Query(int y,int x,int L,int R)
149     {
150         if (ql<=L && R<=qr) return a[y].cnt-a[x].cnt;
151         else
152         {
153             int mid=(L+R)>>1,ans=0;
154             if (ql<=mid) ans+=Query(a[y].ls,a[x].ls,L,mid);
155             if (qr>mid) ans+=Query(a[y].rs,a[x].rs,mid+1,R);
156             return ans;
157         }
158     }
159     int query(int y,int x,int L,int R) {ql=L; qr=R; return Query(y,x,1,n);}
160 }t;
161
162 void solve2()
163 {
164     for (int i=n;i;i--) sa.insert(getnum(s[i]),i);
165     sa.maketree();
166     t.clear(n);
167 //    for (int i=1;i<=sa.Time;i++) cout<<sa.vvv[i]<<' ';cout<<endl;
168     for (int i=1;i<=sa.Time;i++) t.insert(root[i],root[i-1],sa.vvv[i]);
169     int op,x,y,last=0; char c;
170     while (lq--)
171     {
173         if (op==2) continue;
175         while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
176         int xx=0,pp=0; bool flag=1;
177         do
178         {
179             y--;
180             c=getch((getnum(c)+last)%52);
181             if (flag) flag=sa.go(xx,pp,c);
182         }while (((c=getchar())>='a' && c<='z') || (c>='A' && c<='Z'));
183         if (!flag) printf("%d\n",(last=0));
184         else
185         {
186             int R=root[sa.rr[xx]],L=root[sa.ll[xx]-1];
187             printf("%d\n",(last=t.query(R,L,x,y)));
188         }
189     }
190 }
191
192 int main()
193 {
198 }