• #1762. 识别子串(string)


    题意

    内存限制:128 MiB

    时间限制:1000 ms

    $L leq 100000$

    题解
    考虑建出parent树,只有叶子结点上所接受的串在原串中出现一次,而其最长接受的串为原串的一段前缀
    所以对于其叶子结点 $i$ 上在原串中对应着 $[1,len_i]$~$[len_i-len_{fa_i},len_i]$
    所以对于 $[1,len_i-len_{fa_i}]$ 的点,可以把 $len_i$ 作为其右端点,对于 $[len_i-len_{fa_i}+1,len_i]$ 的点,可以把 $len_{fa_i}+1$ 作为包含它的区间长度
    所以开两棵线段树,维护最小右端点和最小长度即可

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e5+5;
    int n,lst=1,sz=1,ans[N];
    char s[N];bool g[N];
    struct SAM{
        int link,len;
        map<int,int>nx;
    }a[N];
    void build(int x){
        int np=++sz,p=lst;
        a[np].len=a[p].len+1;
        while(p && !a[p].nx.count(x))
            a[p].nx[x]=np,p=a[p].link;
        if (!p) a[np].link=1;
        else{
            int q=a[p].nx[x];
            if (a[q].len==a[p].len+1)
                a[np].link=q;
            else{
                int nq=++sz;
                a[nq].len=a[p].len+1;
                a[nq].link=a[q].link;
                a[nq].nx=a[q].nx;
                a[q].link=a[np].link=nq;
                while(p && a[p].nx[x]==q)
                    a[p].nx[x]=nq,p=a[p].link;
            }
        }
        lst=np;
    }
    struct T{
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
        int in[N*2];
        void build(int k,int l,int r){
            in[k]=1e9;if (l==r) return;
            build(Ls,l,mid);build(Rs,mid+1,r);
        }
        void update(int k,int l,int r,int L,int R,int v){
            if (L>R) return;
            if (L<=l && r<=R){in[k]=min(in[k],v);return;}
            if (mid>=L) update(Ls,l,mid,L,R,v);
            if (mid<R) update(Rs,mid+1,r,L,R,v);
        }
        int query(int k,int l,int r,int x,int v){
            if (l==r) return min(v,in[k]);
            if (mid>=x) return query(Ls,l,mid,x,min(v,in[k]));
            return query(Rs,mid+1,r,x,min(v,in[k]));
        }
    }t[2];
    int main(){
        scanf("%s",s+1);n=strlen(s+1);
        for (int i=1;i<=n;i++) build(s[i]-'a');
        for (int i=1;i<=sz;i++) g[a[i].link]=1;
        t[0].build(1,1,n);t[1].build(1,1,n);
        for (int l,r,i=1;i<=sz;i++) if (!g[i])
            r=l=a[i].len,l-=a[a[i].link].len,
            t[0].update(1,1,n,1,l-1,r),
            t[1].update(1,1,n,l,r,r-l+1);
        for (int i=1;i<=n;i++)
            printf("%d
    ",min(t[0].query(1,1,n,i,1e9)-i+1,t[1].query(1,1,n,i,1e9)));
        return 0;
    }
  • 相关阅读:
    7个最好的免费杀毒软件下载
    VMware虚拟机扩容
    tomcat的JK和JK2
    面向对象——接口
    JPA入门样例(採用JPA的hibernate实现版本号)
    JAVA数组的定义及用法
    Styles and Themes
    OpenSSL再曝CCS注入漏洞-心伤未愈又成筛子
    纯文本抽出程序库DMC TEXT FILTER
    数据结构课程设计之通讯录管理系统
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10667008.html
Copyright © 2020-2023  润新知