码迷,mamicode.com
首页 > 编程语言 > 详细

hdu3518 后缀数组

时间:2015-09-08 23:31:06      阅读:314      评论:0      收藏:0      [点我收藏+]

标签:

 题意:求字符串中不重叠的出现至少2次的子串个数。如aaaa 子串有a aa,2个。

普通的求出height[]数组,然后枚举所有的长度差。

对于"baba"

i   height[i]     串

1      0    a

2      1    aba

3      0    ba

4  2    baba

对于可能的k(满足的差),从1开始枚举。对于k=1时,下面的ba baba也是满足的,所以不能直接返回。而是要在不同k的时候计算。

#include<iostream>
#include <string.h>
#include<stdlib.h>
#define LL long long
using namespace std;
#define maxn 1020
int max(int x,int y)
{return x>y?x:y;}
int min(int x,int y)
{return x<y?x:y;}
int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r,int *sa,int n,int 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(j=1,p=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,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}
int Rank[maxn],height[maxn];
void calheight(int *r,int *sa,int 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++);
    return;
}
int r[maxn],sa[maxn];
char s[maxn];
int ok(int k,int n)
{
    int i,j,ret=0;
    int maxx,minx;
    maxx=-1;
    minx=9999999;
    for(i=1;i<=n;i++)
    {
        if(height[i]>=k)//分组满足大于k的
        {
            maxx=max(maxx,sa[i]);
            minx=min(minx,sa[i]);
        }
        else 
        {
            if(maxx-minx>=k)//之前满足条件就要+1;
                ret++;
            maxx=sa[i];
            minx=sa[i];
        }
    }
    if(maxx-minx>=k)
            ret++;
    return ret;
}
int main()
{
    int i,j;
    while(cin>>s)
    {
        if(s[0]==#)break;
        int len=strlen(s);
        for(i=0;i<len;i++)
            r[i]=s[i];
        r[len]=0;
        da(r,sa,len+1,123);
        calheight(r,sa,len);
        LL ans=0;
        for(i=1;i<len;i++)
        {
            ans+=ok(i,len);
        }
        /*for(i=0;i<=len;i++)
        {
            printf("%d %d\n",height[i],sa[i]);
        }*/
        cout<<ans<<endl;
    }
}

 

hdu3518 后缀数组

标签:

原文地址:http://www.cnblogs.com/sweat123/p/4793263.html

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