poj 1743 后缀数组

来源:互联网 发布:最好rss订阅软件 编辑:程序博客网 时间:2024/06/01 18:18

后缀数组,求不可重叠最长重复字串。

#include<iostream>#include<string.h>#include<cmath>#include<algorithm>#include<cstdio>#include<cstring>#define MAXD 21000using namespace std;int r[MAXD], Rank[MAXD], height[MAXD];int sa[MAXD], wa[MAXD], wb[MAXD], WS[MAXD], wv[MAXD];//r数组存放字符的值int cmp(int *p, int x, int y, int l){    return p[x] == p[y] && p[x + l] == p[y + l];}void da(int n, int m)      //n为字符串长度,m为字符的最大值{    int i, j, p, *x = wa, *y = wb, *t;    for(i = 0; i < m; i ++)        WS[i] = 0;    for(i = 0; i < n; i ++)        ++ WS[x[i] = r[i]];    for(i = 1; i < m; i ++)        WS[i] += WS[i - 1];    for(i = n - 1; i >= 0; i --)        sa[-- WS[x[i]]] = i;    for(p = 1, j = 1; p < n; j *= 2, m = p)    {        for(p = 0, i = n - j; i < n; i ++)            y[p ++] = i;        for(i = 0; i < n; i ++)            if(sa[i] >= j)                y[p ++] = sa[i] - j;        for(i = 0; i < n; i ++)            wv[i] = x[y[i]];        for(i = 0; i < m; i ++)            WS[i] = 0;        for(i = 0; i < n; i ++)            ++ WS[wv[i]];        for(i = 1; i < m; i ++)            WS[i] += WS[i - 1];        for(i = n - 1; i >= 0; i --)            sa[-- WS[wv[i]]] = y[i];        for(t = x, x = y, y = t, x[sa[0]] = 0, p = 1, i = 1; i < n; i ++)            x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1: p ++;    }}void calheight(int n)  //n为串的长度减一{    int i, j, k = 0;    for(i = 1; i <= n; i ++)        Rank[sa[i]] = i;    for(i = 0; i < n; height[Rank[i ++]] = k)        for(k ? -- k : 0, j = sa[Rank[i] - 1]; r[i + k] == r[j + k]; k ++);}/*****************以上都是后缀数组模板,下面的是具体问题的处理。******************/int note[MAXD];void input(int n){    int i,j;    scanf("%d",¬e[0]);    for(i=1;i<n;i++)    {        scanf("%d",¬e[i]);        r[i-1]=note[i]-note[i-1]+100;    }    r[n-1]=0;}int judge(int k,int n)          //判断二分值是否满足条件{    int i,num=0;    int MAX=0,MIN=MAXD;    for(i=1;i<=n;i++)    {        if(height[i]>=k)      //不可重叠,k长子串        {            MAX=max(MAX,sa[i]);            MIN=min(MIN,sa[i]);            if(MAX-MIN>k) return 1;        }        else        {            MAX=MIN=sa[i];        }    }    return 0;}int bs(int l,int r)  //二分查找{    int mid;    int n=r;    while(l<=r)    {        mid=(l+r)/2;        if(judge(mid,n))            l=mid+1;        else            r=mid-1;    }    return r;}int main(){    int i,j;    int n;    while(scanf("%d",&n),n)    {        input(n);        da(n,300);        calheight(n-1);        int ans=bs(1,n-1);        if(ans<4) printf("0\n");        else printf("%d\n",ans+1);    }    return 0;}


 

0 0
原创粉丝点击