• 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<<"
    ";
        }
      }
      return 0;
    }
    View Code
  • 相关阅读:
    缓存穿透、缓存雪崩、缓存击穿的区别和解决方案
    图解“红黑树”原理,一看就明白!
    Linux系统中常见文件系统格式
    Maven 加载ojdbc14.jar报错,解决方法
    mybatis中#{}和${}的区别
    SqlServer 分页批按时间排序
    Centos7安装与配置domain模式wildfly(默认配置)
    通过java调用Http接口上传图片到服务器
    Spring boot 配置array,list,map
    idea+springboot+freemarker热部署
  • 原文地址:https://www.cnblogs.com/NicoDafaGood/p/8856704.html
Copyright © 2020-2023  润新知