[字符串HASH][复杂度分析] NOI2017 .Day1 T2 蚯蚓排队

因为k只有50,所以先把所有询问的字符串拆开,加到hash表里,然后用链表模拟整个过程,暴力把新产生的或消失的字符串在hash表里更新答案,复杂度就是对的
具体做法和时间复杂度分析可以看lzz的知乎回答
https://www.zhihu.com/question/62597216

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <assert.h>
#define fi first
#define se second

using namespace std;

typedef unsigned long long Ull;
typedef pair<Ull,int> Ui;

const int N=5e5+10,P=998244353,M=6e6+20,mod=5780347,base=17;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline int rea(int *x){
  char c=nc(); int len=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x[len++]=c-'0',c=nc());
  return len;
}

inline Ull Pow(Ull x,int y){
  Ull ret=1;
  for(;y;y>>=1,x=x*x) if(y&1) ret=ret*x;
  return ret;
}

struct Hashtable{
  int nxt[M],cnt;
  struct nodes{
    Ui val;
    nodes *nxt;
  }node[M],*G[M];
  Ui notf;
  Hashtable(){ cnt=0; notf=Ui(-1,-1);}
  Ui *insert(Ull x){
    int u=x%mod;
    for(nodes *i=G[u];i;i=i->nxt)
      if(i->val.fi==x) return &i->val;
    int cur=++cnt;
    node[cur].val.fi=x; node[cur].val.se=0; node[cur].nxt=G[u]; G[u]=node+cur;
    return &node[cur].val;
  }
  Ui *find(Ull x){
    int u=x%mod;
    for(nodes *i=G[u];i;i=i->nxt)
      if(i->val.fi==x) return &i->val;
    return &notf;
  }
}Ht;

struct works{
  int type;
  vector<Ui*> q;
  int bg,ed,k;
  int x,y;
}Q[N];

int s[M],lst,cur;
struct A{
  int len;
  A *nxt,*pre;
}a[N];
int n,m,maxk;

inline void Modify(A *x,A *y,int d){
  Ull val=0,prod=1; A *cur=x;
  for(int i=1;i<maxk;prod*=base,i++){
    val+=prod*cur->len; 
    Ull key=val; A *now=y;
    for(int j=1;j<=maxk-i;j++){
      key=key*base+now->len;
      Ui *it=Ht.find(key);
      if(*it!=Ht.notf) it->second+=d;
      if(!now->nxt) break;
      now=now->nxt;
    }
    if(!cur->pre) break;
    cur=cur->pre;
  }
}

void print(int x){
  if(x>=10) print(x/10);
  putchar(x%10+'0');
}

int main(){
  rea(n); rea(m);
  for(int i=1;i<=n;i++) rea(a[i].len);
  for(int i=1;i<=m;i++){
    rea(Q[i].type);
    if(Q[i].type==3){
      cur=lst+rea(s+lst); rea(Q[i].k);
      maxk=max(maxk,Q[i].k);
      Q[i].bg=lst; Q[i].ed=cur;
      Ull val=0,pw=Pow(base,Q[i].k);
      for(int j=Q[i].bg;j<Q[i].bg+Q[i].k;j++)
    val=val*base+s[j];
      Q[i].q.push_back(Ht.insert(val));
      for(int j=Q[i].bg+Q[i].k;j<Q[i].ed;j++)
    val=val*base+s[j]-pw*s[j-Q[i].k],Q[i].q.push_back(Ht.insert(val));
    }
    else if(Q[i].type==1) rea(Q[i].x),rea(Q[i].y);
    else rea(Q[i].x);
  }
  for(int i=1;i<=n;i++){
    Ui *it=Ht.find(a[i].len);
    if(*it!=Ht.notf) it->second++;
  }
  for(int k=1;k<=m;k++){
    if(Q[k].type==3){
      int ans=1;
      for(int j=0;j<Q[k].q.size();j++)
    ans=1LL*ans*Q[k].q[j]->se%P;
      print(ans); putchar('\n');
      //printf("%d\n",ans);
    }
    else if(Q[k].type==1){
      Modify(a+Q[k].x,a+Q[k].y,1);
      a[Q[k].x].nxt=a+Q[k].y; a[Q[k].y].pre=a+Q[k].x;
    }
    else{
      Modify(a+Q[k].x,a[Q[k].x].nxt,-1);
      a[Q[k].x].nxt=a[Q[k].x].nxt->pre=0;
    }
  }
  return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值