2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1910 Solved: 539
[ Submit][ Status][ Discuss]
Description
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
Input
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
Output
Sample Input
A
QUERY B
ADD BBABBBBAAB
Sample Output
0
HINT
40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E6 + 2E5 + 233;
int n,Q,mas,rt,last,cnt,len[maxn],par[maxn],g[maxn][26],sum[maxn]
,fa[maxn],pfa[maxn],ch[maxn][2],rev[maxn],Add[maxn];
char c[maxn];
stack <int> st;
void pushdown(int x)
{
if (rev[x])
{
swap(ch[x][0],ch[x][1]);
rev[x] ^= 1;
for (int i = 0; i < 2; i++)
if (ch[x][i]) rev[ch[x][i]] ^= 1;
}
if (Add[x] != 0)
{
sum[x] += Add[x];
for (int i = 0; i < 2; i++)
if (ch[x][i] != 0) Add[ch[x][i]] += Add[x];
Add[x] = 0;
}
}
void rotate(int x)
{
int y = fa[x],z = fa[y];
int d = (ch[y][0] == x)?0:1;
fa[x] = z; fa[y] = x;
pfa[x] = pfa[y]; pfa[y] = 0;
ch[y][d] = ch[x][d^1];
if (ch[y][d]) fa[ch[y][d]] = y;
ch[x][d^1] = y;
if (z) ch[z][ch[z][1] == y] = x;
}
void splay(int x)
{
for (int z = x; z; z = fa[z]) st.push(z);
while (!st.empty()) pushdown(st.top()),st.pop();
for (int y = fa[x]; y; rotate(x),y = fa[x])
if (fa[y])
rotate((ch[fa[y]][0] == y)^(ch[y][0] == x)?x:y);
}
void Access(int x)
{
for (int v = 0; x; v = x,x = pfa[x])
{
splay(x);
if (ch[x][1]) fa[ch[x][1]] = 0,pfa[ch[x][1]] = x;
if (v != 0) pfa[v] = 0,fa[v] = x;
ch[x][1] = v;
}
}
void ChangeRoot(int x)
{
Access(x); splay(x);
rev[x] ^= 1;
}
void Join(int x,int y)
{
ChangeRoot(x); pfa[x] = y;
Access(x); splay(x);
}
void Cut(int x,int y)
{
ChangeRoot(x);
Access(y); splay(y);
fa[x] = ch[y][0] = 0;
}
void LCT_join(int x,int y)
{
Join(x,y); ChangeRoot(rt);
Access(y); splay(y);
sum[y] += sum[x];
if (ch[y][0]) Add[ch[y][0]] += sum[x];
}
void LCT_cut(int x,int y)
{
Cut(x,y); ChangeRoot(rt);
Access(y); splay(y);
sum[y] -= sum[x];
if (ch[y][0]) Add[ch[y][0]] -= sum[x];
}
int New_node(int le,int va)
{
int ret = ++cnt; len[ret] = le;
sum[ret] = va; return ret;
}
void Extend(int w)
{
int p = last,np = New_node(len[p] + 1,1);
while (p && !g[p][w])
g[p][w] = np,p = par[p];
if (!p)
{
par[np] = rt;
LCT_join(np,rt);
last = np; return;
}
int q = g[p][w];
if (len[p] + 1 == len[q])
par[np] = q,LCT_join(np,q);
else
{
int nq = New_node(len[p] + 1,0);
for (int i = 0; i < 26; i++) g[nq][i] = g[q][i];
par[nq] = par[q]; par[q] = par[np] = nq;
LCT_cut(q,par[nq]); LCT_join(q,nq);
LCT_join(np,nq); LCT_join(nq,par[nq]);
while (p && g[p][w] == q)
g[p][w] = nq,p = par[p];
}
last = np;
}
int Getcom(int mas)
{
scanf("%s",c);
int ret = (c[0] == 'A')?1:2;
scanf("%s",c); n = strlen(c);
for (int i = 0; i < n; i++)
{
mas = (mas*131 + i) % n;
swap(c[i],c[mas]);
}
return ret;
}
int main()
{
last = rt = New_node(0,0); cin >> Q;
scanf("%s",c); n = strlen(c);
for (int i = 0; i < n; i++) Extend(c[i] - 'A');
while (Q--)
{
int typ = Getcom(mas);
if (typ == 1)
{
for (int i = 0; i < n; i++) Extend(c[i] - 'A');
}
else
{
int s = rt;
for (int i = 0; i < n && s; i++) s = g[s][c[i] - 'A'];
if (!s) {puts("0"); continue;}
Access(s); splay(s);
mas ^= sum[s];
printf("%d\n",sum[s]);
}
}
return 0;
}