• CodeForces700E Cool Slogans


    感谢dalaoWJZ的讲解。

    我们对于每一个串a[i]相当于在他parent的right集合里找一个出现位置在id-len[x]+len[parent]到id[x]-1区间的

    用主席树判存在性即可。

    至于我问了很久这个区间为什么不能往前判,原因是你每个节点都代表唯一一个子串,所以我们定性查询就可以啦。

    By:大奕哥

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=4e5+10;
     4 int rt[N],num,n;
     5 char s[N];
     6 struct tree{
     7     int l,r;
     8 }t[N*50];
     9 void change(int &x,int l,int r,int p)
    10 {
    11     if(!x)x=++num;
    12     if(l==r)return;
    13     int mid=l+r>>1;
    14     if(p>mid)change(t[x].r,mid+1,r,p);
    15     else change(t[x].l,l,mid,p);
    16 }
    17 void merge(int &x,int y)
    18 {
    19     if(!x||!y){x=x+y;return;}
    20     ++num;t[num]=t[x];x=num;
    21     merge(t[x].l,t[y].l);
    22     merge(t[x].r,t[y].r);
    23 }
    24 bool query(int x,int l,int r,int L,int R)
    25 {
    26     if(!x)return 0;
    27     if(l==L&&r==R)return 1;
    28     int mid=l+r>>1;
    29     if(mid<L)return query(t[x].r,mid+1,r,L,R);
    30     else if(mid>R)return query(t[x].l,l,mid,L,R);
    31     else return query(t[x].l,l,mid,L,mid)|query(t[x].r,mid+1,r,mid+1,R); 
    32 }
    33 struct SAM
    34 {
    35     int cnt,root,last,c[N][26],f[N],dp[N],tt[N],pos[N],r[N],id[N],l[N];
    36     SAM(){cnt=0;last=root=++cnt;}
    37     void add(int x,int dd)
    38     {
    39         int now=last,a=++cnt;last=a;id[a]=dd;
    40         l[a]=l[now]+1;
    41         for(;now&&!c[now][x];now=f[now])c[now][x]=a;
    42         if(!now)f[a]=root;
    43         else{
    44             int q=c[now][x];
    45             if(l[q]==l[now]+1)f[a]=q;
    46             else{
    47                 int b=++cnt;id[b]=dd;
    48                 l[b]=l[now]+1;
    49                 f[b]=f[q];
    50                 f[a]=f[q]=b;
    51                 memcpy(c[b],c[q],sizeof(c[q]));
    52                 for(;now&&c[now][x]==q;now=f[now])c[now][x]=b;
    53             }
    54         }
    55         return;
    56     }
    57     void sort(){
    58         for(int i=1;i<=cnt;++i)tt[l[i]]++;
    59         for(int i=1;i<=n;++i)tt[i]+=tt[i-1];
    60         for(int i=1;i<=cnt;++i)r[tt[l[i]]--]=i;
    61         return;
    62     }
    63     void work()
    64     {
    65         for(int i=cnt;i>=2;--i)
    66         {
    67             int x=r[i];
    68             change(rt[x],1,n,id[x]);
    69             merge(rt[f[x]],rt[x]);
    70         }int ans=1;
    71         for(int i=2;i<=cnt;++i)
    72         {
    73             int x=r[i];
    74             if(f[x]==1){pos[x]=x,dp[x]=1;continue;}
    75             if(query(rt[pos[f[x]]],1,n,id[x]-l[x]+l[pos[f[x]]],id[x]-1))
    76             dp[x]=dp[pos[f[x]]]+1,pos[x]=x;
    77             else dp[x]=dp[pos[f[x]]],pos[x]=pos[f[x]];
    78             ans=max(ans,dp[x]);
    79         }
    80         printf("%d
    ",ans);
    81         return;
    82     }
    83 }A;
    84 int main()
    85 {
    86     scanf("%d%s",&n,s+1);
    87     for(int i=1;i<=n;++i)A.add(s[i]-'a',i);
    88     A.sort();A.work();
    89     return 0;
    90 }
  • 相关阅读:
    Navigator对象关于语言的属性
    对ng-repeat的表格内容添加不同样式:ng-style
    ng-repeat
    ES 6 : 函数的扩展
    二维码下载,区分是 ios 和 android
    gulp配置备份
    [转]移动端web页面使用字体的思考
    移动开发总结
    前端优化:雅虎35条
    input填写银行卡号,每四位空一隔
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8545584.html
Copyright © 2020-2023  润新知