hdu 3518 Boring counting

来源:互联网 发布:ubuntu离线安装ssh 编辑:程序博客网 时间:2024/05/16 17:25

题目链接: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 41000int 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);    }}


 

原创粉丝点击