zoukankan      html  css  js  c++  java
  • Codeforces700E Cool Slogans

    (O(n^4)) 的暴力就是枚举两个子串是不是能满足关系

    然后 (dp) 最长链,显然这东西是铁废物

    (SAM) 上那么转移必然是从父亲向儿子进行的

    那么问题就变成了如何维护出现两次的限制

    本质上出现了两次就是说这个子串的 (endpos) 有至少两个点在上一个子串的所在区间 ([st,ed]) 中出现了

    (还是不熟练,想到这个用了好久)

    线段树合并求 (endpos)(trivial)

    那么可以得到一个 (O((2n)^2log n)) 的做法

    当然可以用一些优化卡过 (n=4000) 的点

    如何进行快速完整的转移

    其实本质上可以在后缀树上倍增,每次暴力跳来找到最大的满足条件的祖先,然后转移即可

    貌似可以证明深度更深的点的答案不会劣于深度浅的点

    不过倍增复杂度不行,那么考虑记录转移点即可

    #include<bits/stdc++.h>
    using namespace std;
    #define reg register
    namespace yspm{
        inline int read(){
            int res=0,f=1; char k;
            while(!isdigit(k=getchar())) if(k=='-') f=-1;
            while(isdigit(k)) res=res*10+k-'0',k=getchar();
            return res*f;
        }
        const int N=4e5+10,M=N*40;
        char s[N];
        int son[N][26],n,rt[N],fa[N],len[N],tot=1,las=1,ls[M],rs[M],sum[M],num;
        inline void push_up(int x){return sum[x]=sum[ls[x]]+sum[rs[x]],void();}
        inline void upd(int &p,int l,int r,int pos){
            if(!p) p=++num; if(l==r) return sum[p]=1,void();
            int mid=(l+r)>>1; if(pos<=mid) upd(ls[p],l,mid,pos); else upd(rs[p],mid+1,r,pos);
            return push_up(p);
        }
        inline int merge(int x,int y,int l,int r){
            if(!x||!y) return x+y; if(l==r) return sum[x]|=sum[y],x;
            int p=++num,mid=(l+r)>>1;
            ls[p]=merge(ls[x],ls[y],l,mid); rs[p]=merge(rs[x],rs[y],mid+1,r);
            return push_up(p),p;
        }
        struct node{int to,nxt;}e[N<<1];
        int head[N],cnt,f[N],ans,fir[N];
        inline void add(int u,int v){return e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt,void();}
        inline void extend(int x,int pos){
            int tmp=las,np=las=++tot; len[np]=len[tmp]+1; upd(rt[np],1,n,pos);
            while(!son[tmp][x]&&tmp) son[tmp][x]=np,tmp=fa[tmp];
            if(!tmp) return fa[np]=1,void();
            int q=son[tmp][x]; if(len[q]==len[tmp]+1) return fa[np]=q,void();
            int clone=++tot; for(reg int i=0;i<26;++i) son[clone][i]=son[q][i]; 
            len[clone]=len[tmp]+1; fa[clone]=fa[q]; fa[q]=fa[np]=clone; 
            while(son[tmp][x]==q) son[tmp][x]=clone,tmp=fa[tmp];
            return ;
        }
        inline void getpos(int x){
            fir[x]=len[x];
            for(reg int i=head[x];i;i=e[i].nxt) getpos(e[i].to),rt[x]=merge(rt[x],rt[e[i].to],1,n),fir[x]=max(fir[x],fir[e[i].to]);
            return ;
        }
        inline int find(int p,int l,int r){
            if(l==r) return l; 
            int mid=(l+r)>>1; 
            if(sum[ls[p]]) return find(ls[p],l,mid); 
            else return find(rs[p],mid+1,r);
        }
        inline int query(int p,int l,int r,int st,int ed){
            if(!p) return 0; if(l==r) return sum[p]; 
            int mid=(l+r)>>1,res=0; 
            if(st<=mid) res+=query(ls[p],l,mid,st,ed);
            if(res>=2) return res;
            if(ed>mid) res+=query(rs[p],mid+1,r,st,ed);
            return res;
        }
        int d[N];
        inline void dfs(int x){
            if(x==1) f[x]=0,d[x]=1;
            else{
                if(query(rt[d[fa[x]]],1,n,fir[x]-len[x]+len[d[fa[x]]],fir[x])>=2) f[x]=f[fa[x]]+1,d[x]=x; 
                else f[x]=f[fa[x]],d[x]=d[fa[x]];
                ans=max(ans,f[x]);
            }for(reg int i=head[x];i;i=e[i].nxt) dfs(e[i].to); return ;
        }
        signed main(){
            scanf("%s",s+1); n=strlen(s+1); 
            for(reg int i=1;i<=n;++i) extend(s[i]-'a',i);
            for(reg int i=2;i<=tot;++i) add(fa[i],i); 
            getpos(1); 
            dfs(1); printf("%d
    ",ans); 
            return 0;
        }
    }
    signed main(){return yspm::main();}
    

    最后记录一个卡常实况

    当我直接 (query o ls) 之后判 (resge 2) 然后返回,快了 (+inf)

  • 相关阅读:
    微信开放平台:OpenAPI、云开发与基础管理能力升级
    腾讯刘颖:从容器到低代码,腾讯云原生技术演进历程
    十年老站长心声:我为什么选择把 Hexo 网站迁移到 Webify
    腾讯云发布微搭生态开放计划,与合作伙伴携手共创产业未来
    SQL Server附加数据库出现错误5123的正确解决方法
    数据分页获取(二)
    Select语句
    数据分页获取(一)
    SQL Server中行转列原理
    QT实现Linux下系统监控小工具之二
  • 原文地址:https://www.cnblogs.com/yspm/p/14203395.html
Copyright © 2011-2022 走看看