zoukankan      html  css  js  c++  java
  • BZOJ2555 Substring

    传送门

    朴素的想法是直接用SAM模拟,但是这样的话每次归并排序会T掉……

    考虑到每次的影响,对于初始的SAM来说,我们每次新加入一个点,那么就会使这个点到(t_0)状态的路径上所有的点全部权值+1,于是我们需要维护路径,同时还需要支持动态插入,那就是LCT了。

    于是乎我们需要用LCT来维护SAM的parent树,其实也不是很难……就是每次在SAM更改parent树的时候LCT照着做就行了。因为这题树不会有什么换根之类的乱七八糟的东西,所以不需要(reverse),不需要(makeroot)……(orz LCT都快忘光了)

    然后也不需要pushup(你也不用维护子树信息啊_) 直接每次在修改的时候打个标记pushdown就好了。

    最后要注意的一点是,在query的时候如果没有匹配要直接退出。然后如果匹配到的话需要先把这个节点splay到根再计算。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(register int i = a;i <= n;i++)
    #define per(i,n,a) for(register int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 600005;
    const int N = 3000005;
    const int INF = 2147483647;
    
    int read()
    {
       int ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    int Q,n,mask;
    char s[N];
    string chars;
    
    void gets(int mask)
    {
       scanf("%s",s),chars = s;
       int k = chars.length()-1;
       rep(j,0,k)
       {
          mask = (mask * 131 + j) % chars.length();
          char t = chars[j];
          chars[j] = chars[mask],chars[mask] = t;
       }
    }
    
    struct LCT
    {
       int ch[M<<1][2],tag[M<<1],val[M<<1],fa[M<<1],top,sta[M<<1];
       bool get(int x) {return ch[fa[x]][1] == x;}
       bool nroot(int x) {return (ch[fa[x]][1] == x) || (ch[fa[x]][0] == x);}
       void add(int x,int y) {if(x) val[x] += y,tag[x] += y;}
       void pushdown(int x)
       {
          if(tag[x] != 0)
          {
    	 int l = ch[x][0],r = ch[x][1];
    	 add(l,tag[x]),add(r,tag[x]),tag[x] = 0;
          }
       }
       void rotate(int x)
       {
          int y = fa[x],z = fa[y],k = get(x);
          if(nroot(y)) ch[z][get(y)] = x;
          fa[x] = z,ch[y][k] = ch[x][k^1],fa[ch[x][k^1]] = y;
          ch[x][k^1] = y,fa[y] = x;
       }
       void splay(int x)
       {
          top = 0;
          int p = x;
          sta[++top] = p;
          while(nroot(p)) p = fa[p],sta[++top] = p;
          while(top) pushdown(sta[top--]);
          while(nroot(x))
          {
    	 int y = fa[x],z = fa[y];
    	 if(nroot(y)) ((ch[z][0] == y) ^ (ch[y][0] == x)) ? rotate(x) : rotate(y);
    	 rotate(x);
          }
       }
       void access(int x) {for(int t = 0;x;t = x,x = fa[x]) splay(x),ch[x][1] = t;}
       void link(int x,int y)
       {
          fa[x] = y;
          access(y),splay(y),add(y,val[x]);
       }
       void cut(int x)
       {
          access(x),splay(x);
          add(ch[x][0],-val[x]);
          fa[ch[x][0]] = 0,ch[x][0] = 0;
       }
    }T;
    
    struct Suffix
    {
       int last,cnt,ch[M<<1][26],fa[M<<1],l[M<<1];
       void extend(int c)
       {
          int p = last,np = ++cnt;
          l[np] = l[p] + 1,last = cnt,T.val[np] = 1;
          while(p && !ch[p][c]) ch[p][c] = np,p = fa[p];
          if(!p) {fa[np] = 1,T.link(np,1);return;}
          int q = ch[p][c];
          if(l[q] == l[p] + 1) fa[np] = q,T.link(np,q);
          else
          {
    	 int nq = ++cnt;
    	 l[nq] = l[p] + 1,memcpy(ch[nq],ch[q],sizeof(ch[q]));
    	 fa[nq] = fa[q],T.link(nq,fa[q]);
    	 fa[np] = fa[q] = nq,T.cut(q),T.link(np,nq),T.link(q,nq);
    	 while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
          }
       }
       void add()
       {
          gets(mask);
          int d = chars.length()-1;
          rep(i,0,d) extend(chars[i] - 'A');
       }
       int query()
       {
          gets(mask);
          int d = chars.length()-1,u = 1;
          rep(i,0,d)
          {
    	 int c = chars[i] - 'A';
    	 if(!ch[u][c]) return 0;
    	 u = ch[u][c];
          }
          T.splay(u);
          return T.val[u];
       }
    }SAM;
    
    int main()
    {
       Q = read(),SAM.last = SAM.cnt = 1;
       scanf("%s",s+1),n = strlen(s+1);
       rep(i,1,n) SAM.extend(s[i] - 'A');
       while(Q--)
       {
          scanf("%s",s);
          if(s[0] == 'A') SAM.add();
          else
          {
    	 int ans = SAM.query();
    	 printf("%d
    ",ans),mask ^= ans;
          }
       }
       return 0;
    }
    
    
  • 相关阅读:
    Redis 5.0 redis-cli --cluster
    Redis使用redis-trib.rb创建带密码的集群问题总结
    Docker实战之Redis-Cluster集群
    kafka作为流式处理的上一层,为什么吞吐量那么大?
    LAMP 实现全过程及wordpress的搭建
    mysql
    Mysql读写分离方案-MySQL Proxy环境部署记录
    Centos7.5部署MySQL5.7基于GTID主从复制+并行复制+半同步复制+读写分离(ProxySQL)
    iptables
    Nginx+Keepalived高可用集群
  • 原文地址:https://www.cnblogs.com/captain1/p/10269545.html
Copyright © 2011-2022 走看看