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

    以POJ 1743为例。模板中的基数排序基于前向星。

    详细证明过程详见 算法合集之《后缀数组——处理字符串的有力工具》。非常不错的一篇论文。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    #include <ctime>
    #include <iomanip>
    
    #pragma comment(linker, "/STACK:1024000000");
    #define EPS (1e-6)
    #define LL long long
    #define ULL unsigned long long
    #define _LL __int64
    #define INF 0x3f3f3f3f
    #define Mod 1000000007
    
    using namespace std;
    
    const int MAXN = 20510;
    
    int s[MAXN];
    
    int Rank[2*MAXN],sa[2*MAXN],tr[2*MAXN],high[MAXN];
    
    struct N
    {
        int v,next;
    }edge[2*MAXN];
    
    int tail[MAXN],Top;
    
    inline void Link(int u,int v)
    {
        edge[Top].v = v;
        edge[Top].next = -1;
        edge[tail[u]].next = Top;
        tail[u] = Top++;
    }
    
    void Get_SA(int *s,int n)
    {
        memset(Rank,0,sizeof(Rank));
        memset(sa,0,sizeof(sa));
    
        int i,j,k,ans,site;
    
        for(i = max(n,200);i >= 0; --i)
            tail[i] = i,edge[i].next = -1;
    
        Top = max(n,200)+1;
    
        for(i = 1; i <= n; ++i)
            Link(s[i],i);
    
        ans = 1,site = 1;
    
        for(i = 0; i <= 200; ++i)
        {
            for(j = edge[i].next; j != -1; j = edge[j].next)
                sa[site++] = edge[j].v,Rank[edge[j].v] = ans;
            if(edge[i].next != -1)
                ans++;
            tail[i] = i,edge[i].next = -1;
        }
    
        for(k = 1;k <= n; k <<= 1)
        {
            Top = n+1;
            for(i = 1;i <= n; ++i)
                Link(Rank[sa[i]+k],sa[i]);
    
            site = 1;
    
            for(i = 0;i <= n; ++i)
            {
                for(j = edge[i].next;j != -1; j = edge[j].next)
                    sa[site++] = edge[j].v;
                tail[i] = i,edge[i].next = -1;
            }
    
            Top = n+1;
    
            for(i = 1;i <= n; ++i)
                Link(Rank[sa[i]],sa[i]);
    
            site = 1;
    
            for(i = 1;i <= n; ++i)
            {
                for(j = edge[i].next;j != -1; j = edge[j].next)
                    sa[site++] = edge[j].v;
                tail[i] = i,edge[i].next = -1;
            }
    
            for(tr[sa[1]] = 1,i = 2,ans = 1;i <= n; ++i)
            {
                if(Rank[sa[i]] != Rank[sa[i-1]] || Rank[sa[i]+k] != Rank[sa[i-1]+k])
                    ans++;
                tr[sa[i]] = ans;
            }
    
            for(i = 1;i <= n; ++i)
                Rank[i] = tr[i];
            if(ans >= n)
                break;
        }
    
        for(i = 1,k = 1;i <= n; ++i)
        {
            if(k) k--;
            if(Rank[i] == 1) {k = 0;high[1] = n-sa[1]+1;continue;}
            j = sa[Rank[i]-1];
            while(i+k <= n && j+k <= n && s[i+k] == s[j+k])
                k++;
            high[Rank[i]] = k;
        }
    //
    //    for(i = 1;i <= n; ++i)
    //        printf("i = %2d SA = %2d Rank = %2d high = %2d
    ",i,sa[i],Rank[i],high[i]);
    
        //以上为Rank。SA,HIGH的构造过程
    }
    
    bool Check(int mid,int n)
    {
        int L = sa[1],R = sa[1],i;
    
        for(i = 2;i <= n; ++i)
        {
            if(high[i] >= mid)
            {
                L = min(sa[i],L),R = max(sa[i],R);
                if(L+mid < R)
                    return true;
            }
            else
            L = sa[i],R = sa[i];
        }
        return false;
    }
    
    int main()
    {
        int i,n;
    
        while(scanf("%d",&n) && n)
        {
            for(i = 1;i <= n; ++i)
                scanf("%d",&s[i]);
    
            for(i = n;i >= 2; --i)
                s[i] -= s[i-1]-100;
    
            Get_SA(s,n);
    
            int mid,anw = 0,Low = 1,High = n;
    
            while(Low <= High)
            {
                mid = (Low + High)>>1;
    
                if(Check(mid,n))
                    anw = max(anw,mid),Low = mid+1;
                else
                    High = mid-1;
            }
    
            printf("%d
    ",anw+1 < 5 ? 0 : anw+1);
        }
        return 0;
    }
    
    
    
    
    
    

  • 相关阅读:
    ExtJs系列教程
    linux 服务器时间 timedatectl命令时间时区操作详解
    aws CloudWatch Events
    AWS Shield
    aws ssm指令
    failed to set bridge addr: "cni0" already has an IP address different from 10.244.0.1/24
    AWS Systems Manager
    Amazon Inspector
    AWS 安全培训
    Amazon Inspector
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7306794.html
Copyright © 2011-2022 走看看