*一道题20

$n \leq 200000$的字符串,$m \leq 200000$次操作:1,末尾加一个字符;2,末尾删一个字符;3,一个区间中,问某个串(新给的)出现次数。强制在线。

并不会。

首先可以通过$nm$的复杂度成功拿到20分。

其次可以写一个不带加字符的:建个后缀树,然后查询就是查:后缀树的一个子树里,有多少编号在一定区间(注意不是询问的区间,右端点需要调整)的后缀。不修改的在线二维数点可以用主席树。也只有20分。

  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
 14 int qread()
 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     {
 35         op=qread();
 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         {
 45             x=qread()^last; y=qread()^last;
 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     {
172         op=qread();
173         if (op==2) continue;
174         x=qread()^last; y=qread()^last; y++;
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 {
194     scanf("%s",s+1); n=strlen(s+1); lq=qread();
195     if (n<=5000 && lq<=5000) solve1();
196     else solve2();
197     return 0;
198 }
View Code

真实做法后缀平衡树,暂时不会。

posted @ 2018-06-15 16:08  Blue233333  阅读(179)  评论(0编辑  收藏  举报