• CF666E Forensic Examination


    题目描述

    题解:

    广义$SAM$+倍增+线段树合并三连。

    对于给出的$m$个串建广义后缀自动机,用线段树合并处理$parent$树子树内所有串出现次数。

    将询问挂在第$pr$位上。

    最后扫一遍原串,记录当前节点以及当前串长,在$parent$树上倍增找$s[pl,pr]$串,最后用线段树查询就好了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 500050;
    typedef long long ll;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    char s[N],s0[N];
    int m,rt[N<<1],q,a1[N],a2[N];
    struct segtree
    {
        int tot,ls[N<<4],rs[N<<4],siz[N<<4],nam[N<<4];
        void update(int u)
        {
            if(siz[ls[u]]<siz[rs[u]])
            {
                nam[u] = nam[rs[u]];
                siz[u] = siz[rs[u]];
            }else
            {
                nam[u] = nam[ls[u]];
                siz[u] = siz[ls[u]];
            }
        }
        void insert(int l,int r,int &u,int qx)
        {
            if(!u)u=++tot;
            if(l==r)
            {
                nam[u] = l;
                siz[u]++;
                return ;
            }
            int mid = (l+r)>>1;
            if(qx<=mid)insert(l,mid,ls[u],qx);
            else insert(mid+1,r,rs[u],qx);
            update(u);
        }
        int merge(int l,int r,int x,int y)
        {
            if(!x||!y)return x+y;
            int z = ++tot,mid = (l+r)>>1;
            if(l==r)siz[z] = siz[x]+siz[y],nam[z] = l;
            else
            {
                ls[z] = merge(l,mid,ls[x],ls[y]);
                rs[z] = merge(mid+1,r,rs[x],rs[y]);
                update(z);
            }
            return z;
        }
        void query(int l,int r,int u,int ql,int qr,int&h1,int&h2)
        {
            if(!u)return ;
            if(l==ql&&r==qr)
            {
                if(h2<siz[u])
                {
                    h1 = nam[u];
                    h2 = siz[u];
                }
                return ;
            }
            int mid = (l+r)>>1;
            if(qr<=mid)query(l,mid,ls[u],ql,qr,h1,h2);
            else if(ql>mid)query(mid+1,r,rs[u],ql,qr,h1,h2);
            else query(l,mid,ls[u],ql,mid,h1,h2),query(mid+1,r,rs[u],mid+1,qr,h1,h2);
        }
    }tr;
    int f[N<<1][22];
    struct Pnt
    {
        int ch[26],len,pre;
    }p[N<<1];
    struct SAM
    {
        int tot,las;
        SAM(){tot=las=1;}
        void init(){las=1;}
        void insert(int c,int i)
        {
            if(p[las].ch[c])
            {
                int lp = las,lq = p[lp].ch[c];
                if(p[lq].len==p[lp].len+1)
                {
                    las = lq;
                    tr.insert(1,m,rt[lq],i);
                }else
                {
                    int nq = ++tot;
                    p[nq] = p[lq];
                    p[nq].len = p[lp].len+1;
                    p[lq].pre = nq;
                    for(;p[lp].ch[c]==lq;lp=p[lp].pre)
                    {
                        p[lp].ch[c] = nq;
                    }
                    tr.insert(1,m,rt[nq],i);
                    las = nq;
                }
                return ;
            }
            int np,nq,lp,lq;
            np = ++tot;
            p[np].len = p[las].len+1;
            tr.insert(1,m,rt[np],i);
            for(lp=las;lp&&!p[lp].ch[c];lp=p[lp].pre)
                p[lp].ch[c]=np;
            if(!lp)p[np].pre = 1;
            else
            {
                lq = p[lp].ch[c];
                if(p[lq].len==p[lp].len+1)p[np].pre = lq;
                else
                {
                    nq = ++tot;
                    p[nq] = p[lq];
                    p[nq].len = p[lp].len+1;
                    p[np].pre = p[lq].pre = nq;
                    for(;p[lp].ch[c]==lq;lp=p[lp].pre)
                        p[lp].ch[c]=nq;
                }
            }
            las = np;
        }
        int hs[N<<1],sta[N<<1];
        void build()
        {
            for(int i=1;i<=tot;i++)hs[p[i].len]++,f[i][0]=p[i].pre;
            for(int i=1;i<=tot;i++)hs[i]+=hs[i-1];
            for(int i=1;i<=tot;i++)sta[hs[p[i].len]--]=i;
            for(int i=tot;i>=1;i--)
                rt[p[sta[i]].pre]=tr.merge(1,m,rt[p[sta[i]].pre],rt[sta[i]]);
            for(int k=1;k<=20;k++)
                for(int i=1;i<=tot;i++)
                    f[i][k]=f[f[i][k-1]][k-1];
        }
    }sam;
    int hed[N],cnt;
    struct EG
    {
        int l,r,pl,id,nxt;
    }e[N];
    void ae(int f,int l,int r,int i,int pl)
    {
        e[++cnt].l = l;
        e[cnt].r = r;
        e[cnt].id = i;
        e[cnt].pl = pl;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
        scanf("%s",s+1);
        read(m);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s0+1);
            int len = strlen(s0+1);
            sam.init();
            for(int j=1;j<=len;j++)
            {
                int c = s0[j]-'a';
                sam.insert(c,i);
            }
        }
        sam.build();
        read(q);
        for(int l,r,pl,pr,i=1;i<=q;i++)
        {
            read(l),read(r),read(pl),read(pr);
            ae(pr,l,r,i,pl);
        }
        int u = 1;
        for(int i=1,lim=strlen(s+1),len=0;i<=lim;i++)
        {
            while(u&&!p[u].ch[s[i]-'a'])u=p[u].pre,len=p[u].len;
            if(!u)u=1,len=0;
            else u=p[u].ch[s[i]-'a'],len++;
            for(int j=hed[i];j;j=e[j].nxt)
            {
                int now = u;
                int ln = i-e[j].pl+1;
                if(len<ln)
                {
                    a1[e[j].id] = e[j].l;
                    continue;
                }
                for(int k=20;k>=0;k--)
                    if(p[f[now][k]].len>=ln)now=f[now][k];
                tr.query(1,m,rt[now],e[j].l,e[j].r,a1[e[j].id]=e[j].l,a2[e[j].id]);
            }
        }
        for(int i=1;i<=q;i++)
            printf("%d %d
    ",a1[i],a2[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Mock工具Mockito教程
    基于Jmeter的自动化测试实施方案
    基于敏捷的测试交付物通用设计
    Jmeter 冒烟测试设计
    Jmockit之mock特性详解
    Sonar 常用代码规则(二)
    从Hg迁移到Git
    使用谷歌colab训练crnn模型
    使用AIstudio训练YOLOv3模型
    阿里云服务器部署Djano+Nginx+uWSGI+conda+Https
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10736910.html
Copyright © 2020-2023  润新知