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

     

  • 相关阅读:
    Android AsyncTask
    Eclipse 快捷键
    Android JSON数据的读取和创建
    Android 原生listview item伸展收缩效果 (续)
    Android 原生listview item伸展收缩效果
    Android listview 禁止滑动
    Android R.layout. 找不到已存在的布局文件
    Android ScrollView
    Android android:clickable 问题
    Codeforces 388C Fox and Card Game (贪心博弈)
  • 原文地址:https://www.cnblogs.com/wang9897/p/9637103.html
Copyright © 2011-2022 走看看