zoukankan      html  css  js  c++  java
  • bzoj4556(sam)

    二分答案,(具体可见http://blog.csdn.net/neither_nor/article/details/51669114),然后就是判定问题,sa和sam都可以做,用sam写了一下,先用sam建后缀树,然后用主席树维护right集合就好了,每次判断把对应节点倍增到深度为mid的点,然后看一下他的子树里有没有right在对应区间的点就好了。

    (前几天用sa写了一下,bz能A,洛谷一直WA,有空重构吧。。。)

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=200010,maxm=4000010;
    int a,b,c,d,t,pos[maxn],cnt=1,cur,fa[maxn],ch[maxn][26],dis[maxn],n,m,tot;
    char s[maxn];
    int add(int c,int p){
        cur=++cnt;dis[cur]=dis[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=cur;
        if(!p)fa[cur]=1;
        else{
            int q=ch[p][c];
            if(dis[q]==dis[p]+1)fa[cur]=q;
            else{
                int nt=++cnt;dis[nt]=dis[p]+1;
                memcpy(ch[nt],ch[q],sizeof(ch[0]));
                fa[nt]=fa[q];fa[q]=fa[cur]=nt;
                for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nt;
            }
        }
        return cur;
    }
    vector<int>tong[maxn];
    int root[maxn],siz[maxn],tim,last[maxn*2],pre[maxn*2],other[maxn*2],f[maxn][25],dfn[maxn],from[maxn];
    void insert(int x,int y){++t;pre[t]=last[x];last[x]=t;other[t]=y;}
    void dfs(int x){
        siz[x]=1;dfn[x]=++tim;from[tim]=x;
        for(int i=last[x];i;i=pre[i]){
            int v=other[i];
            f[v][0]=x;dfs(v);
            siz[x]+=siz[v];
        }
    }
    int jump(int x,int y){
        for(int i=20;i>=0;--i){
            if(dis[f[x][i]]>=y)x=f[x][i];
        }
        return x;
    }
    struct node{
        int l,r,v;
    }tr[maxm];
    void build(int pos,int l,int r,int &x){
        ++tot;tr[tot]=tr[x];x=tot;++tr[x].v;
        if(l==r)return;
        int mid=l+r>>1;
        if(pos<=mid)build(pos,l,mid,tr[x].l);
        else build(pos,mid+1,r,tr[x].r);
    }
    int qs(int i,int j,int l,int r,int L,int R){
        if(r<L||l>R||r<l)return 0;
        if(l>=L&&r<=R)return tr[j].v-tr[i].v;
        int mid=l+r>>1;
        return qs(tr[i].l,tr[j].l,l,mid,L,R)+qs(tr[i].r,tr[j].r,mid+1,r,L,R);
    }
    int pd(int mid){
        int op=jump(pos[c],mid);
        return qs(root[dfn[op]-1],root[dfn[op]+siz[op]-1],1,n,a,b-mid+1);
    }
    int main(){
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        int tmp=1;
        cin>>n>>m;
        scanf("%s",s+1);
        for(int i=n;i>=1;--i){
            tmp=add(s[i]-'a',tmp);
            pos[i]=tmp;
            tong[pos[i]].push_back(i);
        }
        for(int i=2;i<=cnt;++i)insert(fa[i],i);dfs(1);
        for(int j=1;j<=20;++j)
          for(int i=1;i<=cnt;++i){
            f[i][j]=f[f[i][j-1]][j-1];
        }
        for(int i=1;i<=tim;++i){
            int siz=tong[from[i]].size();root[i]=root[i-1];
            for(int j=0;j<siz;++j){
                build(tong[from[i]][j],1,n,root[i]);
            }
        }
        for(int i=1;i<=m;++i){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            int l=1,r=min(d-c+1,b-a+1),ans=0;
            while(l<=r){
                int mid=l+r>>1;
                if(pd(mid))ans=mid,l=mid+1;
                else r=mid-1;
            }
            printf("%d
    ",ans);
        }
        //fclose(stdin);
        //fclose(stdout);
        //system("pause");
        return 0;
    }
    /*
    50 1
    pnzogoobycwczqfrbylxuwkgmnzlekbcakviijcrjahthagkcn
    20 47 8 50
    */
  • 相关阅读:
    编译型语言和解释性语言
    2.变量和基本类型——2.2变量
    2.变量和基本类型——2.1基本内置类型
    1.开始
    机器学习基础—集成学习Bagging 和 Boosting
    C++多态?
    python dataframe数据条件筛选
    UDA机器学习基础—评估指标
    MFC 树形控件
    MFC 列表控件List Control
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8393792.html
Copyright © 2011-2022 走看看