bzoj4943 NOI2017 蚯蚓排队

给出 n 个字符,初始每个字符单独成字符串。支持 m 次操作,每次为一下三种之一:

  • 1 i j:将以 i 结尾的串和以 j 开头的串连到一起。
  • 2 i :将 i 所在串从 i 位置和 i 下一个位置之间断开。
  • 3 S k :对于字符串 S 每个长度为 k 的子串,统计它在这 n 个字符组成所有字符串中出现的次数,求所有统计结果的乘积模 998244353 的结果。

n<=2e5 

m<=3e5

2操作次数小于1e3

Σ|s|<1e7

k<=50

 

因为k<=50,所以一看就知道可以暴力维护每一个子串的hash值

乍一看好像是nk^2的复杂度

实际上只有合并的两个串长度都大于k才会计算k^2次

所以大概就是nk的复杂度

由于nk达到了1e7

所以这里不能用map

可以使用挂链版本的hash表

其实代码不是很难写

但是由于我x和y分不清楚WA了两发

//%std
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define lovelive long long
#define lc son[x][0]
#define rc son[x][1]
#define lowbit(x) (x&(-x))
#define pt vc
const lovelive mod=10233333;
const int N=2e5+100;
const unsigned lovelive base=131;
int head[mod+100],next[mod*2],tot;
lovelive sum[mod*2];
unsigned lovelive a[mod*2];
void add(unsigned lovelive x,int k)
{
  int j=head[x%mod];
  if(!j)
  {
      head[x%mod]=++tot;
      a[tot]=x;
      sum[tot]=k;
      return;
  }
  for(;j;j=next[j])
  {
      if(a[j]==x)
      {
        sum[j]+=k;
        break;
    }
    if(!next[j])
    {
      next[j]=++tot;
      a[tot]=x;
    }
  }
}
lovelive query(unsigned lovelive x)
{
  for(int j=head[x%mod];j;j=next[j])
    if(a[j]==x)
      return sum[j];
  return 0;
}
int pre[N],nxt[N],d[N];
void merge(int i,int j,int k)
{
  unsigned lovelive hash;
  int len;
  for(int x=i;x;x=pre[x])
  {
      len=0;hash=0;
      for(int y=x;y!=j&&y;y=nxt[y])
      {
        ++len;
        hash=hash*base+d[y];
    }
    if(len>=50)
      break;
    for(int y=j;len<50&&y;len++,y=nxt[y])
    {
      hash=hash*base+d[y];
      add(hash,k);
    }
  }
  if(k==-1)
      pre[j]=nxt[i]=0;
  else
  {
      pre[j]=i;
      nxt[i]=j;
  }
}
void read(int &x)
{
  int p=1;
  x=0;
  char c=getchar();
  while(c<'0'||c>'9')
  {
    if(c=='-')
      p=-1;
    c=getchar();
  }
  while(c>='0'&&c<='9')
  {
      x=x*10+c-48;
      c=getchar();
  }
  x*=p;
}
char s[10000010];
unsigned lovelive hsh[10000010],pw[100];
int main()
{
  int n,m,k,opt,x,y,len;
  lovelive ans;
  read(n);read(m);
  for(int i=1;i<=n;i++)
    read(d[i]),add(d[i],1);
  pw[0]=1;
  for(int i=1;i<=50;i++)
    pw[i]=pw[i-1]*base;
  for(int i=1;i<=m;i++)
  {
      read(opt);
      if(opt==1)
      {
        read(x);read(y);
        merge(x,y,1);
    }
    if(opt==2)
    {
      read(x);
      merge(x,nxt[x],-1);
    }
    if(opt==3)
    {
      ans=1;
      scanf("%s",s+1);
      len=strlen(s+1);
      read(k);
      for(int j=1;j<=len;j++)
        hsh[j]=hsh[j-1]*base+s[j]-'0';
      for(int j=0;j<=len-k;j++)
      {
          ans*=query(hsh[j+k]-hsh[j]*pw[k]);
          ans%=998244353;
      }
      cout<<ans<<"\n";
    }
  }
  return 0;
}
View Code

 

posted @ 2018-04-16 16:39  NicoDafaGood  阅读(100)  评论(0编辑  收藏  举报