zoukankan      html  css  js  c++  java
  • hdu 5008 查找字典序第k小的子串

    Boring String Problem

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1848    Accepted Submission(s): 492


    Problem Description
    In this problem, you are given a string s and q queries.

    For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest. 

    A substring si...j of the string s = a1a2 ...an(1 ≤ i ≤ j ≤ n) is the string aiai+1 ...aj. Two substrings sx...y and sz...w are cosidered to be distinct if sx...y ≠ Sz...w
     
    Input
    The input consists of multiple test cases.Please process till EOF. 

    Each test case begins with a line containing a string s(|s| ≤ 105) with only lowercase letters.

    Next line contains a postive integer q(1 ≤ q ≤ 105), the number of questions.

    q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 263, “⊕” denotes exclusive or)
     
    Output
    For each test case, output consists of q lines, the i-th line contains two integers l, r which is the answer to the i-th query. (The answer l,r satisfies that sl...r is the k-th smallest and if there are several l,r available, ouput l,r which with the smallest l. If there is no l,r satisfied, output “0 0”. Note that s1...n is the whole string)
     
    Sample Input
    aaa 4 0 2 3 5
     
    Sample Output
    1 1 1 3 1 2 0 0
    /*
    hdu 5008 查找字典序第k小的子串
    
    problem:
    给你一个字符串,每次寻找字典序第k小的子串(不同的)的开始,结尾坐标。
    
    solve:
    首先可以知道height本身就是按字典序来弄的,对于sa[i-1]和sa[i]而言只要减去
    它们的公共部分即height[i],就是不同的子串.
    可以借此处理出来[1,n]即到字典序第i大的后缀时总共有多少个不同的子串.然后
    利用二分查找就能找到位置
    还要注意就是当有多个的时候输出最小的位置,可以判断当前子串是否是公共前缀的
    一部分.往后枚举找出最小的位置即可
    a
    aa
    aaa
    当你要找最小的串a时可能会找到 3 3.因为它也是aa,aaa的一部分,所以需要枚举一下
    
    hhh-2016-08-12 19:24:38
    */
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <functional>
    #include <map>
    #include <set>
    using namespace std;
    #define lson  (i<<1)
    #define rson  ((i<<1)|1)
    typedef long long ll;
    typedef unsigned int ul;
    const int INF = 0x3f3f3f3f;
    const int  maxn = 100000+10;
    const int mod = 1e9+7;
    
    int t1[maxn],t2[maxn],c[maxn];
    bool cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b] &&r[l+a] == r[l+b];
    }
    
    void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
    {
        n++;
        int p,*x=t1,*y=t2;
        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];
        for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
        for(int j = 1; j <= n; j <<= 1)
        {
            p = 0;
            for(int i = n-j; i < n; i++) y[p++] = i;
            for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
            for(int i = 0; i < m; i++) c[i] = 0;
            for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
            for(int i = 1; i < m; i++) c[i] += c[i-1];
            for(int i = n-1; i >= 0; i--)  sa[--c[x[y[i]]]] = y[i];
    
            swap(x,y);
            p = 1;
            x[sa[0]] = 0;
            for(int i = 1; i < n; i++)
                x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
            if(p >= n) break;
            m = p;
        }
        int k = 0;
        n--;
        for(int i = 0; i <= n; i++)
            Rank[sa[i]] = i;
        for(int i = 0; i < n; i++)
        {
            if(k) k--;
            int j = sa[Rank[i]-1];
            while(str[i+k] == str[j+k]) k++;
            height[Rank[i]] = k;
        }
    
    }
    
    int Rank[maxn],height[maxn];
    int sa[maxn];
    char str[maxn];
    int r[maxn];
    ll num[maxn];
    int lpos,rpos;
    int len ;
    
    
    void fin(ll x)
    {
        int l =1 ,r = len;
        int cur = 0;
        while(l <= r)
        {
            int mid = (l+r) >> 1;
            if(num[mid] >= x)
            {
                cur = mid;
                r = mid-1;
            }
            else
                l = mid+1;
        }
    //    cout << "cur:" <<cur <<endl;
        x = x - num[cur-1];
        lpos = sa[cur]+1;
        rpos = sa[cur]+height[cur]+x;
        int tlen = rpos-lpos+1;
        if(cur+1 <= len && tlen <= height[cur+1])
        {
            for(int i = cur + 1; i <= len; i++)
            {
                if(height[i] >= tlen)
                {
                    if(lpos > sa[i]+1)
                    {
                        lpos = sa[i]+1;
                        rpos = lpos+tlen-1;
                    }
                }
                else
                    break;
            }
        }
        return ;
    }
    
    int main()
    {
        while(scanf("%s",str) != EOF)
        {
            len = strlen(str);
            for(int i = 0; i <len; i ++)
            {
                r[i] = str[i];
            }
            r[len] = 0;
            num[0] = 0;
            get_sa(r,sa,Rank,height,len,200);
            for(int i = 1; i <= len; i++)
            {
                num[i] = (ll)(len - sa[i] - height[i]);
                num[i] += num[i-1];
            }
            int n;
            ll x;
            scanf("%d",&n);
            lpos = 0,rpos = 0;
            for(int i = 1; i <= n; i++)
            {
                scanf("%I64d",&x);
                ll k = (ll)(lpos^rpos^x)+1LL;
    //            cout << "k:" << k <<endl;
                lpos = rpos = 0;
                if(k > num[len])
                {
                    printf("0 0
    ");
                    lpos = 0,rpos = 0;
                    continue;
                }
                fin(k);
                printf("%d %d
    ",lpos,rpos);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    CSS:CSS 创建
    mfs-用户
    java实现扑克牌移动
    java实现扑克牌移动
    java实现扑克牌移动
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
    java实现纵横火柴棋
  • 原文地址:https://www.cnblogs.com/Przz/p/5792183.html
Copyright © 2011-2022 走看看