这个如果单次询问的话应该是个AC自动机裸题
多次询问本来可以按时间分治
但是强制在线
就可以用xhr的二进制分组方法 浅谈数据结构题的几个非经典解法
也可以看CA的博客 【从此不怕强制在线】二进制分组学习笔记
大致思想是修改按二进制分组 这样最多log组 每次询问的复杂度会多一个log 合并的均摊复杂度也是log的
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<Set>
#include<queue>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline int read(char *s){
char c=nc(); int len=0;
for (;!(c>='0' && c<='1');c=nc()) if (c==EOF) return 0;
for (;c>='0' && c<='1';s[++len]=c,c=nc()); s[++len]=0; return len-1;
}
inline void read(char &x){
for (x=nc();x!='+' && x!='?';x=nc());
}
typedef long long ll;
const int K=30;
const int N=200005;
int ch[N][2],cnt[N],fail[N];
int ncnt;
string str[N]; int scnt;
set<string> Set;
int root[K],size[K],tot;
inline void Init(){ ncnt=scnt=tot=0; cl(root); cl(size); Set.clear(); }
inline int newnode(){ return (++ncnt,ch[ncnt][0]=ch[ncnt][1]=cnt[ncnt]=fail[ncnt]=0),ncnt; }
queue<int> Q;
inline void Build(int x){
fail[x]=x; int u,v;
for (int i=0;i<2;i++)
if (!ch[x][i])
ch[x][i]=x;
else
fail[ch[x][i]]=x,Q.push(ch[x][i]);
while(!Q.empty()){
u=Q.front(); Q.pop();
for (int i=0;i<2;i++)
if (!ch[u][i])
ch[u][i]=ch[fail[u]][i];
else
v=ch[u][i],fail[v]=ch[fail[u]][i],cnt[v]+=cnt[fail[v]],Q.push(v);
}
}
inline void Insert(char *s){
if (Set.count(s+1)) return;
Set.insert(s+1); str[++scnt]=string(s+1);
size[++tot]=1;
while (tot>1 && size[tot]==size[tot-1]) size[--tot]*=2,ncnt=root[tot]-1;
root[tot]=newnode();
for(int i=scnt-size[tot]+1;i<=scnt;i++){
int p=root[tot];
for (int j=0;j<str[i].length();j++){
int x=str[i][j]-'0';
if (!ch[p][x]) ch[p][x]=newnode();
p=ch[p][x];
}
cnt[p]++;
}
Build(root[tot]);
}
inline ll Query(char *s){
ll ret=0;
for(int i=1;i<=tot;i++){
int p=root[i];
for(int j=1;s[j];j++)
p=ch[p][s[j]-'0'],ret+=cnt[p];
}
return ret;
}
char tmp[5000005],S[5000005];
int main(){
ll lastans; int T,Q,Case=0,len; char order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(T);
while (T--){
printf("Case #%d:\n",++Case);
lastans=0; Init();
read(Q);
while (Q--){
read(order);
int len=read(tmp);
for (int i=1;i<=len;i++) S[i]=tmp[(i+lastans-1)%len+1]; S[len+1]=0;
if (order=='+')
Insert(S);
else
printf("%lld\n",lastans=Query(S));
}
}
return 0;
}