码迷,mamicode.com
首页 > 其他好文 > 详细

后缀数组

时间:2014-08-21 11:10:23      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   ar   

具体请看论文....

POJ 1743 Musical Theme

不重叠的最长重复子串

bubuko.com,布布扣
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define N 20100
int p[N];
int sa[N],rank[N],height[N];
int wa[N],wb[N],c[N];
//sa[i] 表示排名为i的下标
//rank[i]表示i的排名
//height[i]表示sa[i]和sa[i-1]的最长前缀
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x = wa,*y = wb;
    //初始化基数排序
    for(i = 0;i < m;i ++)
    c[i] = 0;
    for(i = 0;i < n;i ++)
    c[x[i] = s[i]] ++;
    for(i = 1;i < m;i ++)
    c[i] += c[i-1];
    for(i = n-1;i >= 0;i --)
    sa[--c[x[i]]] = i;

    for(j = 1;j <= n;j <<= 1)
    {
        p = 0;
        //y[i] 表示第二关键字排名为i的下标
        for(i = n-j;i < n;i ++)
        y[p++] = i;
        //如果后缀长度不到j的,第二关键字排名靠前
        for(i = 0;i < n;i ++)
        if(sa[i] >= j) y[p++] = sa[i] - j;
        //sa[i] < j的时候不可能为第二关键字,位置sa[i]-j的第二关键字为sa[i],
        //他的排名为p

        //按第一关键字排序
        for(i = 0;i < m;i ++)
        c[i] = 0;
        for(i = 0;i < n;i ++)
        c[x[y[i]]] ++;
        for(i = 1;i < m;i ++)
        c[i] += c[i-1];
        //按y数组的存的下标顺序,基数排序
        for(i = n-1;i >= 0;i --)
        sa[--c[x[y[i]]]] = y[i];

        swap(x,y);
        //生成新的x数组,交换成y,是为了节省空间....
        p = 1;x[sa[0]] = 0;
        //如果两个关键字都一样,下次的第一关键字一样。
        for(i = 1;i < n;i ++)
        x[sa[i]] = y[sa[i-1]] == y[sa[i]]&&y[sa[i-1]+j] == y[sa[i]+j]?p-1:p++;
        if(p >= n) break;
        m = p;
    }

}
void get_height(int s[],int n)
{
    int i,j,k = 0;
    for(i = 1;i <= n;i ++)
    rank[sa[i]] = i;
    //看论文,有证明
    for(i = 0;i < n;i ++)
    {
        if(k) k--;
        j = sa[rank[i]-1];
        while(s[i+k]==s[j+k]) k ++;
        height[rank[i]] = k;
    }
}
int judge(int mid,int n)
{
    int minz,maxz,i;
    minz = maxz = sa[1];
    for(i = 2;i <= n;i ++)
    {
        if(height[i] < mid)
        {
            minz = maxz = sa[i];
        }
        else
        {
            maxz = max(maxz,sa[i]);
            minz = min(minz,sa[i]);
            if(maxz-minz > mid)
            return 1;
        }
    }
    return 0;
}
int main()
{
    int n,i;
    while(scanf("%d",&n)!=EOF)
    {
        if(n == 0) break;
        for(i = 0;i < n;i ++)
        scanf("%d",&p[i]);
        for(i = 0;i < n-1;i ++)
        p[i] = p[i+1] -  p[i] + 90;
        n --;
        p[n] = 0;
        build_sa(p,n+1,200);
        get_height(p,n);
        int str,mid,end;
        str = 1;
        end = n/2;
        while(str < end)
        {
            mid = (str+end + 1)/2;
            if(judge(mid,n))
            str = mid;
            else
            end = mid-1;
        }
        if(end >= 4)
        printf("%d\n",end+1);
        else
        printf("0\n");
    }
    return 0;
}
View Code

 

后缀数组,布布扣,bubuko.com

后缀数组

标签:style   blog   http   color   os   io   for   ar   

原文地址:http://www.cnblogs.com/naix-x/p/3926564.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!