您的位置:首页 > 其它

[后缀数组+枚举] hdu 3518 Boring counting

2014-08-29 17:08 399 查看
题意:找出字符串中至少重复出现两次的不可重叠子串的个数。

思路:同前面的题目一样,这里就不是二分了,而是直接枚举每个子串长度len,在当前的len有多少个子串满足。

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
#define N 1012
int wa
,wb
,wv
,wws
;
int sa
,ra
,height
;
int v
;
int cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int n,int m)
{
    int i,j,p,*x=wa,*y=wb;
    for(i=0;i<m;i++) wws[i]=0;
    for(i=0;i<n;i++) wws[x[i]=v[i]]++;
    for(i=1;i<m;i++) wws[i]+=wws[i-1];
    for(i=n-1;i>=0;i--) sa[--wws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p)
    {
        for(i=n-j,p=0;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++) wws[i]=0;
        for(i=0;i<n;i++) wws[wv[i]]++;
        for(i=1;i<m;i++) wws[i]+=wws[i-1];
        for(i=n-1;i>=0;i--) sa[--wws[wv[i]]]=y[i];
        for(swap(x,y),p=1,i=1,x[sa[0]]=0;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
    }
    return ;
}
void gethei(int n)
{
    int i,j,k=0;
    for(i=1;i<=n;i++) ra[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k) k--;
        j=sa[ra[i]-1];
        while(v[i+k]==v[j+k])
            k++;
        height[ra[i]]=k;
    }
    return ;
}
int main()
{
    char x[1234];
    while(scanf("%s",x),strcmp(x,"#")!=0)
    {
        int i,j;
        int len=strlen(x);
        for(i=0;x[i];i++) v[i]=x[i]-'a'+2;
        v[len]=0;
        da(len+1,30);
        gethei(len);
        int ans=0;
        for(i=1;i<len;i++)
        {
            int MAX=-1,MIN=1002;
            for(j=1;j<=len;j++)
            {
                if(height[j]>=i)
                {
                    MAX=max(max(sa[j-1],sa[j]),MAX);
                    MIN=min(min(sa[j-1],sa[j]),MIN);
                }
                else
                {
                    if(MAX-MIN>=i) ans++;
                    MAX=-1;
                    MIN=1002;
                }
            }
            if(MAX-MIN>=i) ans++;
        }
        printf("%d\n",ans);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: