zoukankan      html  css  js  c++  java
  • bzoj2555 Substring

    题意:给一个字符串后面加若干个字符串或询问某个串的出现次数。强在。

    标程:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm> 
     4 using namespace std;
     5 const int N=1200005;
     6 int son[N][2],ch[N][26],tag[N],sum[N],pre[N],fa[N],sl,ans,mask,n,top,q[N],sc,last,l[N];
     7 char s[N];
     8 int is_rt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
     9 void modi(int x,int y){tag[x]+=y;sum[x]+=y;}
    10 void down(int x)
    11 {
    12     if (tag[x])
    13     {
    14         if (son[x][0]) modi(son[x][0],tag[x]);
    15         if (son[x][1]) modi(son[x][1],tag[x]);
    16         tag[x]=0; 
    17     }
    18 }
    19 void rot(int x)
    20 {
    21    int y=fa[x],z=fa[y],l=(son[y][1]==x),r=l^1;
    22    if (!is_rt(y)) son[z][(son[z][1]==y)]=x;
    23    fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
    24    son[y][l]=son[x][r];son[x][r]=y;
    25 }
    26 void spl(int x)
    27 {
    28     q[top=1]=x;
    29     for (int i=x;!is_rt(i);i=fa[i]) q[++top]=fa[i];
    30     while (top) down(q[top--]);
    31     for (int y;!is_rt(x);rot(x))
    32       if (!is_rt(y=fa[x]))
    33         if ((son[fa[y]][0]==y)^(son[y][0]==x)) rot(x);else rot(y); 
    34 }
    35 void accs(int x){for (int t=0;x;t=x,x=fa[x]) spl(x),son[x][1]=t;}
    36 void link(int x,int y){fa[x]=y;accs(x);spl(x);}
    37 void cut(int x,int y){accs(y);spl(y);fa[x]=son[y][1]=0;}//注意x比y的深度大,x应该在y的右子树 
    38 void sam(int c)
    39 {
    40     int p=last,np=++sc;l[np]=l[p]+1;last=np;
    41     for (;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;
    42     if (!p) pre[np]=1,link(np,1);//注意区分lct和Sam上的father不同 
    43     else {
    44         int q=ch[p][c];
    45         if (l[q]==l[p]+1) pre[np]=q,link(np,q);
    46         else {
    47             int nq=++sc;l[nq]=l[p]+1;
    48             memcpy(ch[nq],ch[q],sizeof(ch[q]));
    49             spl(q);sum[nq]=sum[q]; 
    50             pre[nq]=pre[q];
    51             cut(q,pre[q]);link(nq,pre[q]);
    52             pre[q]=pre[np]=nq;
    53             link(q,nq);link(np,nq);
    54             for (;p&&ch[p][c]==q;p=pre[p]) ch[p][c]=nq; 
    55         }
    56     }
    57     accs(np);spl(np); 
    58     modi(np,1);//np为关键点 
    59 }
    60 void secret(char *s,int mask)
    61 {
    62     sl=strlen(s);
    63     for (int i=0;i<sl;i++)
    64       mask=(mask*131+i)%sl,swap(s[i],s[mask]);
    65 }
    66 void qry(char *s)
    67 {
    68     int now=1;sl=strlen(s);
    69     for (int i=0;i<sl;i++) now=ch[now][s[i]-'A'];
    70     if (!now) puts("0");else spl(now),printf("%d
    ",ans=sum[now]),mask^=ans;
    71 }
    72 int main()
    73 {
    74     scanf("%d%s",&n,s);sl=strlen(s);
    75     sc=last=1;
    76     for (int i=0;i<sl;i++) sam(s[i]-'A');
    77     char op[10];
    78     while (n--)
    79     {
    80         scanf("%s%s",op,s);secret(s,mask);
    81         if (op[0]=='Q') qry(s);
    82         else {
    83            sl=strlen(s);
    84            for (int i=0;i<sl;i++) sam(s[i]-'A');    
    85         }
    86     }
    87     return 0;
    88 }

    题解:后缀自动机+lct

    如果是离线就是二维数点问题。

    在线的话,其实就是求right集合大小嘛,用有根lct动态维护sam的树边。

    每次加入一个新点,就是在到根路径上都+1。打一个加标记即可。

  • 相关阅读:
    怎样用回显和无刷新实现模糊查询?
    2020软件工程作业02
    2020软件工程作业01
    2019春总结作业
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    2019春第一次课程设计实验报告
    2019春第十二周作业
    2019春第十一周作业
  • 原文地址:https://www.cnblogs.com/Scx117/p/8902879.html
Copyright © 2011-2022 走看看