zoukankan      html  css  js  c++  java
  • [USACO06DEC] 牛奶模式Milk Patterns

    题目链接:戳我

    我们知道后缀数组的h数组记录的是后缀i和后缀i-1的最长公共前缀长度,后缀的前缀其实就是子串。

    因为是可以重复出现的子串,所以我们只要计算哪些h数组的长度大于等于x即可。这一步操作我们可以使用二分实现qwq

    为什么可以二分呢?因为我们知道排名相邻越近,后缀相似度越高。然后因为我们要求的还是同一个子串出现的可重复的位置的个数,那么这个子串作为公共前缀,在后缀排序上一定是连续出现的qwq,那么就可以二分了。

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    int n,len,m,p,k;
    int rnk[MAXN],tax[MAXN],h[MAXN],sa[MAXN],tp[MAXN],s[MAXN];
    inline void qsort()
    {
        for(int i=1;i<=m;i++) tax[i]=0;
        for(int i=1;i<=n;i++) tax[rnk[i]]++;
        for(int i=1;i<=m;i++) tax[i]+=tax[i-1];
        for(int i=n;i>=1;i--) sa[tax[rnk[tp[i]]]--]=tp[i];
    }
    inline void suffix_sort()
    {
        m=20001,p=0;
        for(int i=1;i<=n;i++) tp[i]=i,rnk[i]=s[i];
        qsort();
        for(int w=1;p<n;w<<=1,m=p)
        {
            p=0;
            for(int i=1;i<=w;i++) tp[++p]=n-w+i;
            for(int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
            qsort();
            swap(tp,rnk);
            rnk[sa[1]]=p=1;
            for(int i=2;i<=n;i++)
                rnk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&(tp[sa[i]+w]==tp[sa[i-1]+w]))?p:++p;
        }
    }
    inline void get_h()
    {
        int j,k=0;
        for(int i=1;i<=n;i++)
        {
            if(k) k--;
            int j=sa[rnk[i]-1];
            while(s[i+k]==s[j+k]) k++;
            h[rnk[i]]=k;
        }
        // for(int i=1;i<=n;i++) printf("rnk[%d]=%d
    ",i,rnk[i]);
        // for(int i=1;i<=n;i++) printf("h[%d]=%d
    ",i,h[i]);
    }
    inline bool check(int x)
    {
        int cnt=0;
        for(int i=2;i<=n;i++)
        {
            if(h[i]<x) cnt=0;
            else cnt++;
            if(cnt>=k-1) return true;
        }
        return false;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&s[i]);
        suffix_sort();
        get_h();
        int l=1,r=n,ans;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid)==true) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    ssh连接虚拟机centos
    centos安装vim
    CentOS 使用yum命令安装出现错误提示”could not retrieve mirrorlist http://mirrorlist.centos.org
    java多线程之yield,join,wait,sleep的区别
    mybatis分页插件pagehelper
    kaptcha验证码插件使用与参数
    redis主从简单配置
    从本地新建项目到提交到github
    Linux服务器安装rocketMQ单机消息队列
    Oracle通过命令导入数据存储文件
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10742306.html
Copyright © 2011-2022 走看看