zoukankan      html  css  js  c++  java
  • AcWing 140. 后缀数组(hash+二分)

    题目大意:给一个字符串,假设长度为n,那么它就有n个后缀,求排名为i的字典序,并求出排序中相邻串的最长公共前缀。

    题解:hash+二分(假设字符串从1开始)

    如果将n个后缀字符串用sort排序,需要比较nlogn次,每次比较最差需要O(n),所以时间复杂度为O(n^2logn)

    考虑将O(n)的比较用二分优化为log(n)。

    当比较两个字符串时,我们只需要比较它的第一个不相同的位置,所以我们二分最长公共前缀,设为maxlen。

    若str1[maxlen+1]>str2[maxlen+1].则str1的字典序更大。

    用前缀哈希值判断前缀是否相等。 

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    typedef unsigned long long ull; 
    const int N=300000+3;
    const ull base=131;
    
    int len;
    char s[N];
    int sa[N];
    ull f[N],p[N];
    
    ull get_hash(int l,int r)
    {
        return f[r]-f[l-1]*p[r-l+1];
    }
    
    bool check(int x,int a,int b)
    {
        if(get_hash(a,a+x-1)==get_hash(b,b+x-1)) return true;
        else return false;
    }
    
    int get_max_pre(int x,int y)
    {
        int l,r,mid,ans;
        l=0;r=min(len-x+1,len-y+1);
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid,x,y)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        return ans;
    }
    
    bool cmp(int x,int y)
    {
        int max_l=get_max_pre(x,y);
        int xv=s[max_l+x];
        int yv=s[max_l+y];
        return xv<yv;
    }
    
    int main()
    {
        scanf("%s",s+1);
        len=strlen(s+1);
        p[0]=1;
        for(int i=1;i<=len;i++)
        {
            p[i]=p[i-1]*base;
            f[i]=f[i-1]*base+(s[i]-'a'+1);
            sa[i]=i;
        }
        sort(sa+1,sa+len+1,cmp);
        for(int i=1;i<=len;i++) printf("%d ",sa[i]-1);
        printf("
    ");
        for(int i=1;i<=len;i++) printf("%d ",get_max_pre(sa[i],sa[i-1]));
        return 0;
    }
  • 相关阅读:
    在实践中不断总结和提升
    [转]态度的魔力 Net
    回答的智慧 Net
    [转] 【领导必读】唐僧为什么可以领导孙悟空 Net
    [转载]人生感悟:8个笑话 8味人生 Net
    人生成功的十大说话技巧 Net
    最新人生感悟语句摘选 Net
    2012注定是收获的一年,奋斗才刚刚开始
    程序员职业发展的绊脚石思想的枷锁
    AgileEAS.NET5.0界面设计器使用说明书(上)
  • 原文地址:https://www.cnblogs.com/zzyh/p/14785896.html
Copyright © 2011-2022 走看看