zoukankan      html  css  js  c++  java
  • 后缀数组

     #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int maxn = 1e6+7;
    char str[maxn];
    int sa[maxn],tp[maxn],rak[maxn],tax[maxn],a[maxn],M,N;
    //  sa代表着 排名第i小的下标是什么
    //  rak 代表 下标为i的串的排名是什么
    //  顾 rak[sa[i]]==i   sa[rak[i]]=i
    
    void qsort(){
        for(int i=0;i<=M;i++) tax[i]=0;
        for(int i=1;i<=N;i++) tax[rak[i]]++;
        for(int i=1;i<=M;i++) tax[i]+=tax[i-1];
        // 这个循环操作相当于把 在原来sa的基础上 再次按照 tp的rank排名 再排序
        for(int i=N;i>=1;i--) sa[ tax[rak[tp[i]]]-- ]=tp[i];
    }
    void Ssort(){
        M=127;
        for(int i=1;i<=N;i++)rak[i]=a[i],tp[i]=i;
        qsort();
        for(int w=1,p=1; p<N ; M=p,w<<=1)
        {
    
            p=0;
    
            //更新第二关键值
            /**********************************/
            for(int i=N-w+1;i<=N;i++) tp[++p]=i;// 长度越界,第二关键字为0
    
            for(int i=1;i<=N;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
            /**********************************/
            qsort();
    
            // 把 rak里面的数据转移到tp里面
            swap(rak,tp);
    
            //这个操作等于统计了下次需要的桶的个数
            rak[sa[1]]=p=1;
            for(int i=2;i<=N;i++)
                rak[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
        }
    }
    int height[maxn];
    //height[i]为LCP(i,i-1)
    //LCP(i,j)为suff(sa[i])与suff(sa[j])的最长公共前缀
    /*
    LCP的性质
    LCP(i,j)=LCP(j,i);
    LCP(i,i)=len(sa[i])=n-sa[i]+1;
    */
    //LCP(rk[i],rk[k+1])=height[rk[i-1]]-1;
    int get_height()
    {
        int k=0;
        for (int i=1;i<=N;++i) rak[sa[i]]=i;
        for (int i=1;i<=N;++i)
        {
            if (rak[i]==1) continue;//第一名height为0
            if (k) --k;//h[i]>=h[i-1]+1;
            int j=sa[rak[i]-1];
            while (j+k<=N && i+k<=N && a[i+k]==a[j+k]) ++k;
            height[rak[i]]=k;//h[i]=height[rk[i]];
        }
        for (int i=1;i<=N;++i)cout<<height[i]<<endl;
    }
    int main()
    {
        scanf("%s",str);
        N=strlen(str);
        for(int i=1;i<=N;i++)a[i]=str[i-1]-48;
        Ssort();
        for(int i=1;i<=N;i++)
            printf("%d ",sa[i]);
        puts("");
        get_height();
        return 0;
    }
    
    
    ababa
    5 3 1 4 2
    0 1 3 0 2
     #include<stdio.h>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int maxn = 1e6+7;
    char str[maxn];
    int sa[maxn],tp[maxn],rak[maxn],tax[maxn],a[maxn],M,N;
    //  sa代表着 排名第i小的下标是什么
    //  rak 代表 下标为i的串的排名是什么
    //  顾 rak[sa[i]]==i   sa[rak[i]]=i
    
    void qsort(){
        for(int i=0;i<=M;i++) tax[i]=0;
        for(int i=1;i<=N;i++) tax[rak[i]]++;
        for(int i=1;i<=M;i++) tax[i]+=tax[i-1];
        // 这个循环操作相当于把 在原来sa的基础上 再次按照 tp的rank排名 再排序
        for(int i=N;i>=1;i--) sa[ tax[rak[tp[i]]]-- ]=tp[i];
    }
    void Ssort(){
        M=127;
        for(int i=1;i<=N;i++)rak[i]=a[i],tp[i]=i;
        qsort();
        for(int w=1,p=1; p<N ; M=p,w<<=1)
        {
    
            p=0;
    
            //更新第二关键值
            /**********************************/
            for(int i=N-w+1;i<=N;i++) tp[++p]=i;// 长度越界,第二关键字为0
    
            for(int i=1;i<=N;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
            /**********************************/
            qsort();
    
            // 把 rak里面的数据转移到tp里面
            swap(rak,tp);
    
            //这个操作等于统计了下次需要的桶的个数
            rak[sa[1]]=p=1;
            for(int i=2;i<=N;i++)
                rak[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
        }
    }
    int height[maxn];
    //height[i]为LCP(i,i-1)
    //LCP(i,j)为suff(sa[i])与suff(sa[j])的最长公共前缀
    /*
    LCP的性质
    LCP(i,j)=LCP(j,i);
    LCP(i,i)=len(sa[i])=n-sa[i]+1;
    */
    //LCP(rk[i],rk[k+1])=height[rk[i-1]]-1;
    int get_height()
    {
        int k=0;
        for (int i=1;i<=N;++i) rak[sa[i]]=i;
        for (int i=1;i<=N;++i)
        {
            if (rak[i]==1) continue;//第一名height为0
            if (k) --k;//h[i]>=h[i-1]+1;
            int j=sa[rak[i]-1];
            while (j+k<=N && i+k<=N && a[i+k]==a[j+k]) ++k;
            height[rak[i]]=k;//h[i]=height[rk[i]];
        }
        for (int i=1;i<=N;++i)cout<<height[i]<<endl;
    }
    int main()
    {
        scanf("%s",str);
        N=strlen(str);
        for(int i=1;i<=N;i++)a[i]=str[i-1]-48;
        Ssort();
        for(int i=1;i<=N;i++)
            printf("%d ",sa[i]);
        puts("");
        get_height();
        return 0;
    }
    
    
    ababa
    5 3 1 4 2
    0 1 3 0 2
  • 相关阅读:
    swiper.js 点击链接跳转后再次返回到轮播原位置
    KVO和KVC
    XML与HTML的区别
    iOS UIAppearance使用详解
    文件处理
    IOS 四种数据永久保存的方式
    UIImage图片处理(更改颜色,修改透明度,缩小,合并图片)
    从一个视图控制器切换到另一个视图控制器的几种方式
    NSString的常用方法
    NSURLRequest和NSURLConnection
  • 原文地址:https://www.cnblogs.com/DWVictor/p/10283179.html
Copyright © 2011-2022 走看看