HDU 3518 Boring counting(後綴數組入門題)

題目鏈接:點擊打開鏈接

Boring counting

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2617    Accepted Submission(s): 1062


Problem Description
035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover,such apearances can not overlap each other.
Take aaaa as an example.”a” apears four times,”aa” apears two times without overlaping.however,aaa can’t apear more than one time without overlaping.since we can get “aaa” from [0-2](The position of string begins with 0) and [1-3]. But the interval [0-2] and [1-3] overlaps each other.So “aaa” can not take into account.Therefore,the answer is 2(“a”,and “aa”).
 

Input
The input data consist with several test cases.The input ends with a line “#”.each test case contain a string consists with lower letter,the length n won’t exceed 1000(n <= 1000).
 

Output
For each test case output an integer ans,which represent the answer for the test case.you’d better use int64 to avoid unnecessary trouble.
 

Sample Input
aaaa ababcabb aaaaaa #
 

Sample Output
2 3 3
 
題意:求至少出現兩次的不重疊子串的數目總和。後綴數組入門,但是我不會告訴你我wa了多少次。注意的地方寫在代碼裏。

AC代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int wa[200005],wb[200005],wv[200005],ws[200005];
int r[200005],height[200005],rank1[200005],sa[200005];
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;
}
void calheight(int *r,int *sa,int n){
    int i,j,k=0;
    for(i=1;i<=n;i++) rank1[sa[i]]=i;
    for(i=0;i<n;height[rank1[i++]]=k)
        for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
    return;
}
int main()
{
    int i,j,len;char s[1100];
    while(scanf("%s",s)!=EOF&&s[0]!='#')
    {
       len=strlen(s);
       for(i=0;i<len;i++)
       r[i]=s[i];
       r[len]=0;
       da(r,sa,len+1,300);
       calheight(r,sa,len);
       int Max,Min,ans=0;
       for(i=1;i<=len;i++)
       {
         Max=sa[1],Min=sa[1];
         for(j=2;j<=len;j++)
         {
            if(height[j]>=i)
            {
              Max=max(Max,max(sa[j-1],sa[j]));
              Min=min(Min,min(sa[j-1],sa[j]));
            }
            else
            {
              if(Max-Min>=i) ans++;
              Max=sa[j],Min=sa[j];
            }
         }
        if(Max-Min>=i) ans++;//可能從來沒有進入過else裏面,因此要加一個判斷。

       }
       printf("%d\n",ans);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章