zoukankan      html  css  js  c++  java
  • BZOJ4556: [Tjoi2016&Heoi2016]字符串

    题解:  首先对于原串建SAM 我们考虑对于每次查询区间[c,d] 我们考虑二分答案 然后我们只需判定[a,b]中是否会产生这个子串即可 首先我们可以倍增在parent树上找到包含这个子串的节点 然后只需判断其子树中叶子节点是否出现在[a-mid+1,b]中 这个可以通过线段树合并来实现即可

    /**************************************************************
        Problem: 4556
        User: c20161007
        Language: C++
        Result: Accepted
        Time:9004 ms
        Memory:92912 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=2e5+10;
    #define link(x) for(edge *j=h[x];j;j=j->next)
    using namespace std;
    int dis[MAXN],fa[MAXN][21],ch[MAXN][26],vis[MAXN];
    int cur,cnt,rt,pos[MAXN],n,m;
    char str[MAXN];
    struct edge{int t;edge*next;}e[MAXN],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    int Rt[MAXN];
    void built(int x,int id){
        int last=cur;cur=++cnt;int p=last;dis[cur]=id;vis[cur]=1;pos[id]=cur;
        for(;p&&!ch[p][x];p=fa[p][0])ch[p][x]=cur;
        if(!p)fa[cur][0]=rt;
        else{
            int q=ch[p][x];
            if(dis[q]==dis[p]+1)fa[cur][0]=q;
            else{
                int nt=++cnt;dis[nt]=dis[p]+1;
                memcpy(ch[nt],ch[q],sizeof(ch[q]));
                fa[nt][0]=fa[q][0];fa[q][0]=fa[cur][0]=nt;
                for(;ch[p][x]==q;p=fa[p][0])ch[p][x]=nt;
            }
        }
    }
    typedef struct node{int l,r,sum;}node;
    node d[MAXN*21];int cnt1;
    void merge(int &x,int y,int l,int r){
        if(!y)return ;
        if(!x){x=y;return ;}
        int t=++cnt1;d[t]=d[x];d[t].sum+=d[y].sum;x=t;
        if(l==r)return ;
        int mid=(l+r)>>1;
        merge(d[x].l,d[y].l,l,mid);
        merge(d[x].r,d[y].r,mid+1,r);
    }
    void update(int &x,int l,int r,int t){
        if(!x)x=++cnt1;
        d[x].sum++;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update(d[x].l,l,mid,t);
        else update(d[x].r,mid+1,r,t);
    }
    int a,b,ans1;
    void querty(int x,int l,int r,int ql,int qr){
        if(!x)return;
        if(ql<=l&&r<=qr){ans1+=d[x].sum;return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)querty(d[x].l,l,mid,ql,qr);
        if(qr>mid)querty(d[x].r,mid+1,r,ql,qr);
    }
    void dfs(int x,int pre){
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        link(x){
            if(j->t!=pre){
                dfs(j->t,x);
                merge(Rt[x],Rt[j->t],1,n);
            }
        }
        if(vis[x])update(Rt[x],1,n,dis[x]);
        ans1=0;querty(Rt[6],1,n,1,2);
    }
    bool check(int mid,int c){
        int t=c+mid-1;int x=pos[t];
        for(int i=20;i>=0;i--){
            if(dis[fa[x][i]]>=mid)x=fa[x][i];
        }
        if(a+mid-1>b)return false;
        ans1=0;querty(Rt[x],1,n,a+mid-1,b);
        if(ans1>0)return true;
        return false;
    }
    int main(){
        scanf("%d%d",&n,&m);
        scanf("%s",str+1);rt=cnt=cur=1;cnt1=0;
        for(int i=1;i<=n;i++)built(str[i]-'a',i);
        for(int i=1;i<=cnt;i++)add(fa[i][0],i);
        dfs(rt,0);int l1,r1,l2,r2;
        while(m--){
            scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
            int l=1;int r=r2-l2+1;int ans=0;a=l1;b=r1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(check(mid,l2))ans=mid,l=mid+1;
                else r=mid-1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    

     

    4556: [Tjoi2016&Heoi2016]字符串

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 1563  Solved: 627
    [Submit][Status][Discuss]

    Description

    佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
    一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
    O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
    共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?

    Input

    输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
    m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
    字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n
     

    Output

     对于每一次询问,输出答案。

    Sample Input

    5 5
    aaaaa
    1 1 1 5
    1 5 1 1
    2 3 2 3
    2 4 2 3
    2 3 2 4

    Sample Output

    1
    1
    2
    2
    2

     

  • 相关阅读:
    Linq to OBJECT延时标准查询操作符
    LINQ to XML
    动态Linq(结合反射)
    HDU 1242 dFS 找目标最短路
    HDu1241 DFS搜索
    hdu 1224 最长路
    BOJ 2773 第K个与m互质的数
    ZOJ 2562 反素数
    2016 ccpc 杭州赛区的总结
    bfs UESTC 381 Knight and Rook
  • 原文地址:https://www.cnblogs.com/wang9897/p/9637103.html
Copyright © 2011-2022 走看看