hdu 3518 Boring counting

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518

题目大意:求重复次数大于等于2的不覆盖的子串个数。

题目思路:这个题比较好,我的做法是直接从1到n检查height数组,如果比height[i-1]小,说明前面有一部分子串不能在后而找到相同的子串了,处理之。。这个过程中要维护两个数组,以便检查是否合法。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define M 41000
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b)
{
	return a<b?a:b;
}
int height[M],rank[M],r[M],sa[M];
int ts[M],ta[M],tb[M],tv[M],pos;
int mi[M],ma[M];
bool cmp(int *y,int a,int b,int l)
{
    return y[a]==y[b]&&y[a+l]==y[b+l];
}
void da(int n,int m)
{
    int i,j,*x=ta,*y=tb,p;
    for(i=0;i<m;i++) ts[i]=0;
    for(i=0;i<n;i++) ts[x[i]=r[i]]++;
    for(i=1;i<m;i++) ts[i]+=ts[i-1];
    for(i=n-1;i>=0;i--) sa[--ts[x[i]]]=i;

    for(j=1,p=1;p<n;j*=2,m=p)
    {
        p=0;
        for(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<m;i++) ts[i]=0;
        for(i=0;i<n;i++) tv[i]=x[y[i]];
        for(i=0;i<n;i++) ts[tv[i]]++;
        for(i=1;i<m;i++) ts[i]+=ts[i-1];
        for(i=n-1;i>=0;i--) sa[--ts[tv[i]]]=y[i];
        swap(x,y);
        x[sa[0]]=0;
        p=1;
        for(i=1;i<n;i++)
        {
            if(cmp(y,sa[i-1],sa[i],j)) x[sa[i]]=p-1;
            else x[sa[i]]=p++;
        }
    }
}
void calh(int n)
{
    int i,k,tmp;
    for(i=1;i<=n;i++) rank[sa[i]]=i;
    k=0;
    for(i=0;i<n;i++)
    {
        tmp=sa[rank[i]-1];
        for(;r[i+k]==r[tmp+k];k++)
        ;
        height[rank[i]]=k;
        k?--k:0;
    }
}
char s[M];
int main()
{
    int i,j,k,len;
    while(scanf("%s",s)!=EOF)
    {
        if(s[0]=='#') break;
        len=strlen(s);
        for(i=0;i<len;i++)
            r[i]=s[i]-'a'+1;
        r[i]=0;
        da(len+1,27);
        calh(len);
        int ans=0;
        if(len>=2)
        {
            for(j=1;j<=height[2];j++)
            {
                mi[j]=sa[1];
                ma[j]=sa[1];
            }
        }
        for(i=2;i<=len;i++)
        {
            if(height[i]<height[i-1])
            {
                for(j=height[i]+1;j<=height[i-1];j++)
                {
                    if(ma[j]-mi[j]>=j)
                        ans++;
                }
            }
            for(j=1;j<=height[i];j++)
            {
                mi[j]=min(mi[j],sa[i]);
                ma[j]=max(ma[j],sa[i]);
            }
            if(i==len) continue;
            for(j=height[i]+1;j<=height[i+1];j++)
            {
                mi[j]=sa[i];
                ma[j]=sa[i];
            }
        }
        for(j=1;j<=height[len];j++)
        {
            if(ma[j]-mi[j]>=j)
                ans++;
        }
        printf("%d\n",ans);
    }
}


 

你可能感兴趣的:(hdu 3518 Boring counting)