zz:https://www.cnblogs.com/ljh2000-jump/p/6880362.html
考虑每次加入删除对出现次数的影响只会加减一,那么我可以先用Trie来维护整个问题中出现的字符串,然后对于每个节点我都记录一下以当前串为前缀的字符串个数,同时开个vector维护出现次数为x时的最早时刻。因为每次修改只会加减一,那么空间与字符串长度同级,这个用vector实现很方便。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int MAXN = 100011;
int n,ch[MAXN*60][10],c[MAXN*60],len,S,cnt,ans;
char s[MAXN];
vector<int>w[MAXN*60];
inline int getint()
{
int w=0,q=0;
char c=getchar();
while((c<'0'||c>'9') && c!='-')
c=getchar();
if(c=='-')
q=1,c=getchar();
while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
}
inline void work()
{
n=getint();
S=cnt=1;
int type,u,now;
LL x,A,B,C;
for(int o=1;o<=n;o++)
{
type=getint();
u=S;
scanf("%s",s);
len=strlen(s);
if(type==1)
{
for(int i=0;i<len;i++)
{
now=s[i]-'a';
if(!ch[u][now])
ch[u][now]=++cnt;
u=ch[u][now];
c[u]++;//记下每个点经过的次数
if(c[u]>(int)w[u].size())
//记下每个前缀首次出现某个次数时的时间
w[u].push_back(o);
}
}
else if(type==2)
{
for(int i=0;i<len;i++)
{
now=s[i]-'a';
u=ch[u][now];
c[u]--;
}
}
else {
u=S;
scanf("%lld%lld%lld",&A,&B,&C);
ans=abs(ans);//!!!
x=1LL*ans*A%C; x+=B; x%=C;
ans=0;
for(int i=0;i<len;i++)
{
now=s[i]-'a';
if(!ch[u][now]) { ans=-1; break; }
u=ch[u][now];
}
if(ans!=-1)
{
if((int)w[u].size()<=x)
ans=-1;
else
ans=w[u][x];
}
printf("%d
",ans);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("selection.in","r",stdin);
freopen("selection.out","w",stdout);
#endif
work();
return 0;
}
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
#define M 6000050
int n,ans=0;
char s[65];
struct Trie
{
int tot,siz[M],ch[M][12];
vector<int>v[M];
void insert(int k)
{
int len = strlen(s+1),u=0;
for(int i=1;i<=len;i++)
{
siz[u]++;
if(v[u].size()<siz[u])v[u].push_back(k);
int c = s[i]-'a'+1;
if(!ch[u][c])ch[u][c]=++tot;
u=ch[u][c];
}
siz[u]++;
if(v[u].size()<siz[u])v[u].push_back(k);
}
void erase()
{
int len = strlen(s+1),u=0;
for(int i=1;i<=len;i++)
{
siz[u]--;
int c = s[i]-'a'+1;
u=ch[u][c];
}
siz[u]--;
}
int query(int k)
{
int len = strlen(s+1),u=0;
for(int i=1;i<=len;i++)
{
int c = s[i]-'a'+1;
u=ch[u][c];
}
if(v[u].size()<=k)return -1;
return v[u][k];
}
}tr;
int main()
{
scanf("%d",&n);
for(int opt,a,b,c,i=1;i<=n;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%s",s+1);
tr.insert(i);
}
if(opt==2)
{
scanf("%s",s+1);
tr.erase();
}
if(opt==3)
{
scanf("%s%d%d%d",s+1,&a,&b,&c);
int tmp =(int)((1ll*a*abs(ans)+b)%c);
printf("%d
",ans=tr.query(tmp));
}
}
return 0;
}