zoukankan      html  css  js  c++  java
  • Codeforces 1037H Security sam+线段树合并

    Codeforces 1037H Security

    题意

    给一个长度为(n)的字符串(s)(q)次询问,每次询问给出两个整数(l,r)和一个字符串(x),你要在区间([l,r])中找到(s)的一个子串满足其字典序大于(x),输出满足条件的子串中字典序最小的子串,找不到输出(-1)

    (nle 10^5,qle 2cdot 10^5,sum |s|le 2cdot 10^5)

    分析

    用线段树维护后缀自动机上每个点(u)的终点集合(endpos(u)),对于每个询问,枚举(x)的每个前缀在(sam)上转移,再尝试去在后面添加一个更大的字符(c),判断转移到的点的(endpos)集合中有没有([l,r])中的点,有则更新答案。

    Code

    #include<bits/stdc++.h>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,rs[p]
    #define pii pair<int,int>
    #define lson l,mid,ls[p]
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=4e5+10;
    const int inf=1e9;
    int n,m;
    char s[N],t[N];
    vector<int>g[N];
    struct SegmentTree{
        int tr[N*40],ls[N*40],rs[N*40],tot;
        void up(int x,int l,int r,int &p){
            if(!p) p=++tot;
            tr[p]++;
            if(l==r) return;
            int mid=l+r>>1;
            if(x<=mid) up(x,lson);
            else up(x,rson);
        }
        int merge(int x,int y,int l,int r){
            if(!x||!y) return x+y;
            int o=++tot,mid=l+r>>1;
            if(l==r) tr[o]=tr[x]+tr[y];
            else{
                ls[o]=merge(ls[x],ls[y],l,mid);
                rs[o]=merge(rs[x],rs[y],mid+1,r);
                tr[o]=tr[ls[o]]+tr[rs[o]];
            }
            return o;
        }
        int qy(int dl,int dr,int l,int r,int p){
            if(!p||l>r) return 0;
            if(l==dl&&r==dr) return tr[p];
            int mid=l+r>>1;
            if(dr<=mid) return qy(dl,dr,lson);
            else if(dl>mid) return qy(dl,dr,rson);
            else return qy(dl,mid,lson)+qy(mid+1,dr,rson);
        }
    }seg;
    struct SAM{
        int last,cnt;int ch[N][26],fa[N],len[N],rt[N];
        void insert(int c,int pos){
            int p=last,np=++cnt;last=np;len[np]=len[p]+1;
            for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
            if(!p) fa[np]=1;
            else {
                int q=ch[p][c];
                if(len[q]==len[p]+1) fa[np]=q;
                else  {
                    int nq=++cnt;len[nq]=len[p]+1;
                    memcpy(ch[nq],ch[q],sizeof ch[q]);
                    fa[nq]=fa[q],fa[q]=fa[np]=nq;
                    for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
                }
            }
            seg.up(pos,1,n,rt[np]);
        }
        void init(){
            last=cnt=1;
        }
        void dfs(int u){
            for(int x:g[u]){
                dfs(x);
                rt[u]=seg.merge(rt[u],rt[x],1,n);
            }
        }
        void gao(){
            for(int i=2;i<=cnt;i++) g[fa[i]].pb(i);
            dfs(1);
        }
        void solve(int l,int r){
            int u=1;
            t[m+1]='a'-1;
            pii ans=mp(-1,-1);
            for(int i=1;i<=m+1;i++){
                for(int j=t[i]-'a'+1;j<26;j++){
                    int x=ch[u][j];
                    if(!x) continue;
                    int pos=seg.qy(l+i-1,r,1,n,rt[x]);
                    if(pos){
                        ans=mp(i,j);
                        break;
                    }
                }
                if(i==m+1||!ch[u][t[i]-'a']) break;
                u=ch[u][t[i]-'a'];
            }
            if(ans==mp(-1,-1)) puts("-1");
            else{
                t[ans.fi]=0;
                printf("%s%c
    ",t+1,ans.se+'a');
            }
        }
    }sam;
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        sam.init();
        for(int i=1;i<=n;i++) sam.insert(s[i]-'a',i);
        sam.gao();
        int q,l,r;
        scanf("%d",&q);
        while(q--){
            scanf("%d%d",&l,&r);
            scanf("%s",t+1);
            m=strlen(t+1);
            sam.solve(l,r);
        }
        return 0;
    }
    
  • 相关阅读:
    常用知识点集合
    LeetCode 66 Plus One
    LeetCode 88 Merge Sorted Array
    LeetCode 27 Remove Element
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 448 Find All Numbers Disappeared in an Array
    LeetCode 219 Contains Duplicate II
    LeetCode 118 Pascal's Triangle
    LeetCode 119 Pascal's Triangle II
    LeetCode 1 Two Sum
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13887952.html
Copyright © 2011-2022 走看看