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

    题目大意:

    给你一个串,问至少出现k次的子串的长度最大是多少。

    解题思路:

    这个子串的长度必然是原串k个不同后缀的LCP。

    建后缀数组,求出height。

    然后二分答案,每次在height里扫一遍即可。

    C++ Code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,k,t1[20002],t2[20002],c[1000002],sa[20002],s[20002],rk[20002],height[20002];
    inline int min(int a,int b){return a<b?a:b;}
    inline void sa_sort(){
        int*x=t1,*y=t2,m=1000000;
        memset(c,0,sizeof c);
        for(int i=1;i<=n;++i)++c[x[i]=s[i]];
        for(int i=1;i<=m;++i)c[i]+=c[i-1];
        for(int i=n;i;--i)sa[c[x[i]]--]=i;
        for(int k=1;k<=n;k<<=1){
            int p=0;
            for(int i=n-k+1;i<=n;++i)y[++p]=i;
            for(int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k;
            for(int i=0;i<=m;++i)c[i]=0;
            for(int i=1;i<=n;++i)++c[x[y[i]]];
            for(int i=1;i<=m;++i)c[i]+=c[i-1];
            for(int i=n;i;--i)sa[c[x[y[i]]]--]=y[i];
            int*tmp=x;x=y,y=tmp;
            x[sa[p=1]]=1;
            for(int i=2;i<=n;++i)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p;
            if(p==n)break;
            m=p;
        }
    }
    inline void get_height(){
        for(int i=1;i<=n;++i)rk[sa[i]]=i;
        for(int i=1,k=0;i<=n;++i){
            if(rk[i]==1)continue;
            if(k)--k;
            int j=sa[rk[i]-1];
            while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])++k;
            height[rk[i]]=k;
        }
    }
    bool check(int x){
        int nw=1,len=1<<30;
        for(int i=2;i<=n;++i){
            int mn=min(len,height[i]);
            if(mn>=x){
                if(++nw==k)return true;
                len=mn;
            }else{
                nw=1;
                len=1<<30;
            }
        }
        return false;
    }
    int main(){
        ios::sync_with_stdio(0),cin.tie(0);
        cin>>n>>k;
        if(k==1)return!printf("%d
    ",n);
        for(int i=1;i<=n;++i)cin>>s[i];
        sa_sort();
        get_height();
        int l=0,r=20001,ans=0;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid))l=(ans=mid)+1;else
            r=mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    串口打印信息
    网上下的ARM入门笔记
    职业生涯规划之驱动开发笔试题
    哈佛学生是如何度过大学4年的
    9G忠告打基础
    新塘M0Timer定时器篇
    ARM裸机篇按键中断
    linux驱动面试题
    裸机程序循环加法操作
    ARM裸机篇串口UART实验
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9605183.html
Copyright © 2011-2022 走看看