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
  • 相关阅读:
    AcWing 1027. 方格取数 dp
    AcWing 1014. 登山 dp
    acwing 482. 合唱队形 dp
    LeetCode 1463. 摘樱桃II dp
    LeetCode 100. 相同的树 树的遍历
    LeetCode 336. 回文对 哈希
    LeetCode 815. 公交路线 最短路 哈希
    算法问题实战策略 DARPA大挑战 二分
    算法问题实战策略 LUNCHBOX 贪心
    AcWing 1100. 抓住那头牛 BFS
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4442386.html
Copyright © 2011-2022 走看看