后缀数组 poj. 1743. Musial Theme

来源:互联网 发布:黑帽seo如何赚钱 编辑:程序博客网 时间:2024/06/07 04:46

题意感觉有点难懂。但就是问你,给你一个数字串,然后问有没有相同子串(不能重合且长度大于五),或者不用相同的,全部加上一个或减去一个数之后相等的就好。
先是二分长度,然后通过height数组来判断是否可行

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include<string>using namespace std;const int  maxn =4e4+10;int n;struct Suffix{    int s[maxn];    int SA[maxn],ranked[maxn],height[maxn];    int x[maxn],y[maxn],buc[maxn],len,m;    void init(int *str)    {        //len=strlen(str);        len=n;        for(int i=0;i<len;i++) s[i]=(int)str[i];        m=200;//    }    void build()    {        for (int i = 0; i < m; i++) buc[i] = 0; // buc 是一个桶        for (int i = 0; i < len; i++) buc[x[i] = s[i]]++;        for (int i = 1; i < m; i++)             buc[i] += buc[i - 1];        for (int i = len - 1; i >= 0; i--)            SA[--buc[x[i]]] = i;        for (int k = 1; k <= len; k <<= 1) { // k 倍增          int p = 0;          //对第二关键字排序,y[i]:第i大的第二关键字是谁          // 后缀 len - k 及之后的所有后缀第二关键字最小。为0          for (int i = len - 1; i >= len - k; i--)            y[p++] = i;          for (int i = 0; i < len; i++)                if (SA[i] >= k)                    y[p++] = SA[i] - k;         //总体来排个序,求出SA          for (int i = 0; i < m; i++) buc[i] = 0;          for (int i = 0; i < len; i++)                buc[x[y[i]]]++;          for (int i = 1; i < m; i++)                buc[i] += buc[i - 1];          for (int i = len - 1; i >= 0; i--)                SA[--buc[x[y[i]]]] = y[i];          swap(x, y);          p = 1; x[SA[0]] = 0;          // 重新计算每个一元的名次。则x数组里存的是总体的顺序          for (int i = 1; i < len; i++) {            if (y[SA[i - 1]] == y[SA[i]] && y[SA[i - 1] + k] == y[SA[i] + k])              x[SA[i]] = p - 1;            else x[SA[i]] = p++;          }          if (p >= len) break; // 每个后缀的名次已经完全不同,不需要继续倍增              m = p; // 更新名次的最大值。        }    }    void LCP()    {        for(int i=0;i<len;i++)            ranked[SA[i]]=i;        int k=0;        for(int i=0;i<len;i++)        {            if(ranked[i]==0) {height[0]=0;continue;}            if(k) k--;            int j=SA[ranked[i]-1];            while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;            height[ranked[i]]=k;        }    } /*  int LCS(char *s1)    {        int l=strlen(s1);        s1[l]=' ';        scanf("%s",s1+l+1);        init(s1);        build();        LCP();        int ans=0;        for(int i=1;i<len;i++)        if((SA[i-1]<l&&SA[i]>l)||(SA[i-1]>l&&SA[i]<l))                ans=max(ans,height[i]);        return ans;    }*/};Suffix a;int ok(int mid){    int i=1;    while(1){    for(;i<n;i++)        if(a.height[i]>=mid)            break;    if(i>=n) break;    int minn=a.SA[i-1];    int maxx=a.SA[i-1];    while(i<n&&a.height[i]>=mid)    {        minn=min(a.SA[i],minn);        maxx=max(a.SA[i],maxx);        i++;    }    if(maxx-minn>=mid) return 1;    }    return 0;}int num[maxn];int str[maxn];int main(){    while(scanf("%d",&n)!=EOF&&n)    {       memset(str,0,sizeof(str));      memset(num,0,sizeof(num));        for(int i=0;i<n;i++)            scanf("%d",&num[i]);        if(n<10) printf("0\n");        else        {            for(int i=1;i<n;i++)                str[i-1]=num[i]-num[i-1]+100;             n--;         //   str[n-1]=0;            a.init(str);            a.build();            a.LCP();            int l=4,r=n/2,res=0;            while(l<=r)            {                int mid=l+(r-l)/2;                if(ok(mid)){                    res=mid;                    l=mid+1;                }                else r=mid-1;            }            if(res>=4)            printf("%d\n",res+1);            else printf("0\n");        }    }    return 0;}
原创粉丝点击