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

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

#include 
#include 
#include 
#include 
#include 
#define fi first
#define se second

using namespace std;

typedef unsigned long long Ull;
typedef pairint> 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 ¬f;
  }
}Ht;

struct works{
  int type;
  vector 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;ilen; 
    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;jfor(int j=Q[i].bg+Q[i].k;jelse 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;j1LL*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;
}

你可能感兴趣的:(哈希,字符串)