http://www.elijahqi.win/archives/3891
题面:http://uoj.ac/problem/315
正解 hash表模数参考了gxz巨佬的
正解就是在暴力的基础上发现我们只需要一开始提前把需要询问的串放入hash表 即可
这样hash表的总数不会太大 因为其他的字符串都不会出现在询问中
这题是复杂度分析的问题 考虑假如没有 2操作那么复杂度是稳的n*k问题就在于我每次分开之后会产生c*k^2的复杂度再次合并的时候也仅仅会产生c*k^2的复杂度
所以暴力也可以拿到很多的分
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int mod=998244353;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=5e5+10;
const int S=1e7+10;
const int g1=1117;
int n,m,cnt;ull p1[N];char s2[S];
inline int reads(){
char ch=gc();while(!isdigit(ch)) ch=gc();int op=0;
while(isdigit(ch)) ++op,s2[++cnt]=ch,ch=gc();return op;
}
struct node{
int pre,nxt,nm;
}data[N];
struct node1{
int op,x,y,to;
}qr[N];
namespace hst{
const int mod=10233333;int h[mod];
struct node{
ull s;int nm,next;
}data[20000010];
int num;
inline void init(ull s){
int x=s%mod;
for (int i=h[x];i;i=data[i].next){
if (data[i].s==s) return;
}
data[++num].next=h[x];data[num].s=s;h[x]=num;
}
inline void insert1(ull s){
int x=s%mod;
for (int i=h[x];i;i=data[i].next)
if (data[i].s==s){++data[i].nm;return;}
}
inline void del1(ull s){
int x=s%mod;
for (int i=h[x];i;i=data[i].next)
if (data[i].s==s){--data[i].nm;return;}
}
inline int query(ull s){
int x=s%mod;
for (int i=h[x];i;i=data[i].next){
if (data[i].s==s){return data[i].nm;}
}return 0;
}
}
int main(){
freopen("b.in","r",stdin);
n=read();m=read();int k=50;p1[0]=1;
for (int i=1;i<=55;++i) p1[i]=p1[i-1]*g1;
for (int i=1;i<=n;++i) {
int s1=read();data[i].pre=data[i].nxt=i;data[i].nm=s1;
}
for (int owo=1;owo<=m;++owo){
int op=read();qr[owo].op=op;
if (op==1) qr[owo].x=read(),qr[owo].y=read();
if (op==2) qr[owo].x=read();
if (op==3){
int lst=cnt;qr[owo].y=lst;
int nn=reads();int kk=read();qr[owo].x=kk;qr[owo].to=cnt;
ull hs1=0;
for (int i=lst+1;i<=lst+kk;++i){
hs1=hs1*g1+s2[i]-'0';
}hst::init(hs1);
for (int i=lst+kk+1;i<=cnt;++i){
hs1=hs1-p1[kk-1]*(s2[i-kk]-'0');
hs1=hs1*g1+s2[i]-'0';
hst::init(hs1);
}
}
}
for (int i=1;i<=n;++i){
int s1=data[i].nm;hst::insert1(s1);
}
for (int owo=1;owo<=m;++owo){
int op=qr[owo].op;
if (op==1){
int x=qr[owo].x,y=qr[owo].y,lst=x;
data[y].pre=x;data[x].nxt=y;int cnt=1;
while(cnt<k){
int tot=1,now=lst;ull hs1=0;
hs1+=data[lst].nm;now=data[now].nxt;
while(tot<k){++tot;
hs1=hs1*g1+data[now].nm;
if (tot>cnt) hst::insert1(hs1);
if (data[now].nxt==now) break;
now=data[now].nxt;
}
if(lst==data[lst].pre) break;
lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
}
}
if (op==2){
int id=qr[owo].x,nxt=data[id].nxt;//puts("--");
data[nxt].pre=nxt;
int cnt=1,lst=id;
while(cnt<k){
int tot=1,now=lst;ull hs1=0;
hs1+=data[lst].nm;now=data[now].nxt;
while(tot<k){++tot;
hs1=hs1*g1+data[now].nm;
if(tot>cnt) hst::del1(hs1);
if (data[now].nxt==now) break;
now=data[now].nxt;
}
if (lst==data[lst].pre) break;
lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
}
data[id].nxt=id;
}
if (op==3){
int lst=qr[owo].y;int kk=qr[owo].x;int to=qr[owo].to;
ull hs1=0;
for (int i=lst+1;i<=lst+kk;++i){
hs1=hs1*g1+s2[i]-'0';
}ll ans=1;
ans=ans*hst::query(hs1)%mod;
for (int i=lst+kk+1;i<=to;++i){
hs1=hs1-p1[kk-1]*(s2[i-kk]-'0');
hs1=hs1*g1+s2[i]-'0';
ans=ans*hst::query(hs1)%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}
我的第一发暴力:
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=5e5+10;
const int S=1e7+10;
const int g=1113;
const int g1=1117;
const int hsmod1=998244353;
const int hsmod=1e9+7;
int n,m;ll p[N],p1[N];char s1[2],s2[S];
struct node{
int pre,nxt,nm;
}data[N];
namespace hst{
const int mod=100003;int h[55][mod],num[55];
struct node{
int s,nm,next;
}data[51][500001];
inline void insert1(int s,int s1,int k){
int x=s%mod;//printf("%d\n",s);
for (int i=h[k][x];i;i=data[k][i].next){
if (data[k][i].s==s1){
++data[k][i].nm;return;
}
}
data[k][++num[k]].next=h[k][x];data[k][num[k]].nm=1;data[k][num[k]].s=s1;
h[k][x]=num[k];
}
inline void del1(int s,int s1,int k){
int x=s%mod;//printf("%d\n",s);
for (int i=h[k][x];i;i=data[k][i].next){
if (data[k][i].s==s1){
--data[k][i].nm;return;
}
}
}
inline int query(int s,int s1,int k){
int x=s%mod;//printf("%d\n",s);
for (int i=h[k][x];i;i=data[k][i].next){
if (data[k][i].s==s1){
return data[k][i].nm;
}
}return 0;
}
}
int main(){
//freopen("b.in","r",stdin);
n=read();m=read();p[0]=1;int k=50;p1[0]=1;
for (int i=1;i<=n;++i) p[i]=p[i-1]*g%hsmod;
for (int i=1;i<=n;++i) p1[i]=p1[i-1]*g1%hsmod1;
for (int i=1;i<=n;++i) {
scanf("%s",s1);data[i].pre=data[i].nxt=i;
data[i].nm=s1[0]-'0';hst::insert1(s1[0]-'0',s1[0]-'0',1);
}//int fd=0;
for (int owo=1;owo<=m;++owo){
int op=read();
if (op==1){
int x=read(),y=read(),lst=x;
data[y].pre=x;data[x].nxt=y;int cnt=1;
while(cnt<k){
int tot=1,now=lst;ll hs=0,hs1=0;
hs+=data[lst].nm;now=data[now].nxt;hs1=hs;
while(tot<k){++tot;
hs=(hs*g+data[now].nm)%hsmod;
hs1=(hs1*g1+data[now].nm)%hsmod1;
if (tot>cnt) hst::insert1(hs,hs1,tot);
if (data[now].nxt==now) break;
now=data[now].nxt;
}
if(lst==data[lst].pre) break;
lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
}
}
if (op==2){
int id=read(),nxt=data[id].nxt;//puts("--");
data[nxt].pre=nxt;
int cnt=1,lst=id;
while(cnt<k){
int tot=1,now=lst;ll hs=0,hs1=0;
hs+=data[lst].nm;now=data[now].nxt;hs1=hs;
while(tot<k){++tot;
hs=(hs*g+data[now].nm)%hsmod;
hs1=(hs1*g1+data[now].nm)%hsmod1;
if(tot>cnt) hst::del1(hs,hs1,tot);
if (data[now].nxt==now) break;
now=data[now].nxt;
}
if (lst==data[lst].pre) break;
lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
}
data[id].nxt=id;
}
if (op==3){
//++fd;
scanf("%s",s2+1);int kk=read();
ll hs=0,hs1=0;
//printf("%s\n",s2+1);int nn=strlen(s2+1);
for (int i=1;i<=kk;++i){
hs=(hs*g+s2[i]-'0')%hsmod;
hs1=(hs1*g1+s2[i]-'0')%hsmod1;
}ll ans=1;
ans=ans*hst::query(hs,hs1,kk)%mod;
for (int i=kk+1;s2[i];++i){
hs=((hs-p[kk-1]*(s2[i-kk]-'0')%hsmod)%hsmod+hsmod)%hsmod;
hs=(hs*g+s2[i]-'0')%hsmod;
hs1=((hs1-p1[kk-1]*(s2[i-kk]-'0')%hsmod1)%hsmod1+hsmod1)%hsmod1;
hs1=(hs1*g1+s2[i]-'0')%hsmod1;
ans=ans*hst::query(hs,hs1,kk)%mod;
}
printf("%lld\n",ans);
//if(fd==249) {printf("%s\n",s2+1);printf("%d\n",kk);return 0;}
}
//for (int i=1;i<=50;++i) printf("%d ",hst::num[i]);puts("");
}
return 0;
}