zoukankan      html  css  js  c++  java
  • bzoj2555: SubString

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #define maxn 1200005
      7 #define maxl 3000005
      8 using namespace std;
      9 
     10 int q,n,tot,root,last,mark,m,ri[maxn],lazy[maxn];
     11 char st[maxl];
     12 void watch(){
     13     int temp=mark;
     14     for (int i=1;i<=m;i++){
     15         temp=(temp*131+i-1)%m+1;
     16         char t=st[i]; st[i]=st[temp],st[temp]=t,temp--;
     17     }
     18 }
     19 struct Date{
     20     int fa[maxn],son[maxn][2];
     21     int which(int x){
     22         return son[fa[x]][1]==x;
     23     }
     24     bool isroot(int x){
     25         return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
     26     }
     27     void change(int x,int y){
     28         ri[x]+=y,lazy[x]+=y;
     29     }
     30     void pushdown(int x){
     31         if (lazy[x]==0) return;
     32         if (son[x][0]) change(son[x][0],lazy[x]);
     33         if (son[x][1]) change(son[x][1],lazy[x]);
     34         lazy[x]=0;
     35     }
     36     void relax(int x){
     37         if (!isroot(x)) relax(fa[x]);
     38         pushdown(x);
     39     }
     40     void rotata(int x){
     41         int y=fa[x],dd=which(y),d=which(x);
     42         if (!isroot(y)) son[fa[y]][dd]=x; fa[x]=fa[y];
     43         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1];
     44         fa[y]=x,son[x][d^1]=y;
     45     }
     46     void splay(int x){
     47         relax(x);
     48         while (!isroot(x)){
     49             if (isroot(fa[x])) rotata(x);
     50             else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
     51             else rotata(x),rotata(x);
     52         }
     53     }
     54     void access(int x){
     55         for (int p=0;x;x=fa[x]){
     56             splay(x);
     57             son[x][1]=p;
     58             p=x;
     59         }
     60     }
     61     void link(int x,int y){
     62         fa[x]=y,access(y),splay(y),change(y,ri[x]);
     63     }
     64     void cut(int x){
     65         access(x),splay(x),change(son[x][0],-ri[x]),fa[son[x][0]]=0,son[x][0]=0;
     66     }
     67 }lct;
     68 struct Tsegment{
     69     int fa[maxn],son[maxn][26],dist[maxn];
     70     void prepare(){tot=root=last=1;memset(lazy,0,sizeof(lazy)); memset(ri,0,sizeof(ri));}
     71     int newnode(int x){
     72         dist[++tot]=x; return tot;
     73     }
     74     void add(int x){
     75         int p=last,np=newnode(dist[last]+1); last=np,ri[np]=1;
     76         for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
     77         if (p==0) fa[np]=root,lct.link(np,root);
     78         else{
     79             int q=son[p][x];
     80             if (dist[p]+1==dist[q]) fa[np]=q,lct.link(np,q);
     81             else{
     82                 int nq=newnode(dist[p]+1); ri[nq]=0;
     83                 memcpy(son[nq],son[q],sizeof(son[q]));
     84                 fa[nq]=fa[q]; lct.cut(q),lct.link(nq,fa[nq]);
     85                 fa[q]=fa[np]=nq; lct.link(q,nq),lct.link(np,nq);
     86                 for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
     87             }
     88         }
     89     }
     90     void build(){
     91         for (int i=1;i<=m;i++) add(st[i]-'A');
     92     }
     93     void query(){
     94         int x,y;
     95         bool can=1;
     96         x=root;
     97         for (int i=1;i<=m;i++){
     98             y=st[i]-'A';
     99             if (!son[x][y]){
    100                 can=0;
    101                 break;
    102             }else{
    103                 x=son[x][y];
    104             }
    105         }
    106         if (can==0||x==root) puts("0");
    107         else{
    108             lct.splay(x);
    109             printf("%d
    ",ri[x]),mark^=ri[x];
    110         }
    111     }
    112 }SAM;
    113 
    114 int main(){
    115     scanf("%d",&q),mark=0;
    116     scanf("%s",st+1),m=strlen(st+1);
    117     SAM.prepare();
    118     SAM.build();
    119     while (q--){
    120         scanf("%s",st+1);
    121         if (st[1]=='A') scanf("%s",st+1),m=strlen(st+1),watch(),SAM.build();
    122         else scanf("%s",st+1),m=strlen(st+1),watch(),SAM.query();
    123     }
    124     return 0;
    125 }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2555

    题目大意:给你一个字符串init,要求你支持两个操作
    (1):在当前字符串的后面插入一个字符串
    (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
    你必须在线支持这些操作。

    做法:如果没有操作1,显然kmp,ac自动机,后缀自动机都可以轻松解决,用后缀自动机的话,就是对原串建立SAM,匹配串在上面匹配,若失配,则输出0,否则一直跳,假设最后跳到了x节点,答案就是,这个状态的right值。right值为parent树中以该节点为根的子树中right值的和,静态的显然比较好维护,但本题是动态加串,由于SAM是用增量法构建的,显然可以维护这个SAM,但是right则不怎么好维护,看了题解后,发现parent树毕竟是一棵树,那显然可以用lct来维护right值。操作2与静态的类似。恶心的就是这题的解密。

    后缀自动机+lct。

  • 相关阅读:
    P3973 [TJOI2015]线性代数
    P3168 [CQOI2015]任务查询系统
    二次剩余学习笔记
    URL注入攻击+知识星球资源整理
    我的网络安全架构知识点的总结(待完善)
    Sudo提权
    DNSlog平台各种利用姿势(盲注)
    Wireshark抓包理论加实操
    Fofa搜索技巧(理论加实践的整理)
    Windows留后门维持权限(其中包括详细的telnet改端口与连接)
  • 原文地址:https://www.cnblogs.com/OYzx/p/5550874.html
Copyright © 2011-2022 走看看