zoukankan      html  css  js  c++  java
  • 后缀数组 --- WOj 1564 Problem 1564

     Problem 1564 - A - Circle

    Problem's Link:   http://acm.whu.edu.cn/land/problem/detail?problem_id=1564


    Mean: 

    给你一个长度不超过1e6的数字串,求第k大的环状数字串的前面那个位置。

    analyse:

    好吧,我承认这是个水题,比赛的时候sb了,因为原来做过后缀自动机求解字符串的环状最小表示法,所以一直用后缀自动机的知识去套k小表示法,比赛的时候太固执了。

    这题就是后缀数组的sa[]数组的运用,sa[i]=k表示的是字符串所有的后缀按字典序排序后,第i个后缀排在第k个。

    那么我们只需将数字串复制一遍接在原串后面(环状),对s求一遍后缀数字得到sa数组,然后找到sa<=n的第k个sa,那么sa[i]-1就是答案。

    为什么?看这张图:

    连接后的字符串我们可以得到2*n个字符串,但是我们只需关心前n个字符串就可,因为后面的n个字符串其实根本没作用,他们只相当于前n个字符串的前缀的重复出现而已。

    所以我们只需要找到满足sa[i]<=n的第k个就行,sa[i]-1就是答案。

    Time complexity: O(n)

    Source code:  

    //  Memory   Time
    //  1347K     0MS
    //   by : crazyacking
    //   2015-04-20-19.00
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<cstdlib>
    #include<cstring>
    #include<climits>
    #include<iostream>
    #include<algorithm>
    #define MAXN 1000010
    #define LL long long
    using namespace std;
    const int maxn = 2002000;
    int Rank[maxn],wb[maxn],wv[maxn],wss[maxn];
    
    bool cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b] && r[a+l]==r[b+l];
    }
    
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=Rank,*y=wb,*t;
        for(i=0;i<m;i++) wss[i]=0;
        for(i=0;i<n;i++) wss[x[i]=r[i]]++;
        for(i=1;i<m;i++) wss[i]+=wss[i-1];
        for(i=n-1;i>=0;i--)
           sa[--wss[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p)
        {
            for(p=0,i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<n;i++) wv[i]=x[y[i]];
            for(i=0;i<m;i++) wss[i]=0;
            for(i=0;i<n;i++) wss[wv[i]]++;
            for(i=1;i<m;i++) wss[i]+=wss[i-1];
            for(i=n-1;i>=0;i--) sa[--wss[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
        return;
    }
    
    char s[maxn];
    int r[maxn],sa[maxn];
    int main()
    {
        int n,k;
        while(~scanf("%d %d",&n,&k))
        {
                getchar();
                gets(s);
                int len = strlen(s),i;
                for(int i=len;i<len*2;++i) s[i]=s[i-len];
                s[len*2]='';
                len=len*2;
            for(int i=0;i<len;++i)
                    s[i]+='a'-'0';
            len++;
            for(i=0; i<len-1; i++)
                r[i] = s[i]-'a'+1;
            r[len-1] = 0;
            da(r,sa,len,30);
            int idx=0;
            for(int i=1;i<len;++i)
            {
                    if(sa[i]+1<=n)
                    {
                            idx++;
                            if(idx==k) printf("%d
    ",sa[i]!=0?sa[i]:n);
                    }
            }
        }
        return 0;
    }
    View Code
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #define MAXN 1000010
    using namespace std;
    int n,k,len,si,now;
    char s[MAXN];
    vector<int> num;
    int GetAns(vector<int>tp,int tk,int l)
    {
            if(tp.size()==1 || l==n-1) return tp[0];
            vector<int> cnt[10];
            si=tp.size();
            for(int i=0;i<si;++i)
                    cnt[s[ (tp[i]+l)%n ]-'0'].push_back(tp[i]);
            now=0;
            while(tk>cnt[now].size())
            {
                    tk-=cnt[now].size();now++;
            }
            return GetAns(cnt[now],tk,l+1);
    }
    int main()
    {
            while(~scanf("%d %d",&n,&k))
            {
                    scanf("%s",s);
                    len=strlen(s);
                    num.clear();
                    for(int i=1;i<=len;++i) num.push_back(i);
                    printf("%d
    ",GetAns(num,k,0));
            }
            return 0;
    }
    View Code
  • 相关阅读:
    【POJ3358】Period of an Infinite Binary Expansion-欧拉定理+数论好题
    【POJ3696】The Luckiest Number-欧拉定理+快速幂
    【POJ3090】Visible Lattice Points-欧拉函数应用
    【POJ3090】Visible Lattice Points-欧拉函数应用
    【POJ2891】Strange Way to Express Integers-解一元线性同余方程组
    【POJ2891】Strange Way to Express Integers-解一元线性同余方程组
    【POJ2429】GCD & LCM Inverse-Pollard-rho分解+枚举
    【POJ2429】GCD & LCM Inverse-Pollard-rho分解+枚举
    【POJ1811】Prime Test-Miller-Rabin素数测试+Pollard-rho大数分解
    deleted
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4442386.html
Copyright © 2011-2022 走看看