hdu3518 后缀数组的height应用

height[i] 表示 排第i的子串和第i-1的子串的最长公共前缀,对于某一个长度k,如果存在连续一段height值大于等于k且起始位置的最远距离大于等于k,这一段就存在一个解,ans加1

#include<stdio.h>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define repp(i,j,k) for(int i=j;i<k;i++)
const int N=2e3+10;
const int MOD=1e9+7;
const int inf=1e9;
int n,m,k,up,p;
char s[N];
int f[N],sa[N],cnt[N],sr[N],r[N],height[N];
int len;
void getSa(){
    int up=0;
    rep(i,len) up=max(up,(int)s[i]);
    up++;
    rep(i,up) cnt[i]=0;
    rep(i,len)  cnt[f[i]=s[i]]++;
    repp(i,1,up) cnt[i]+=cnt[i-1];
    for(int i=len-1;i>=0;i--) sa[--cnt[f[i]]]=i;



    int d=1,p=0;
    while(d<len){
        repp(i,len-d,len) sr[p++]=i;
        rep(i,len) if(sa[i]>=d) sr[p++]=sa[i]-d;
        rep(i,up) cnt[i]=0;
        rep(i,len) cnt[f[sr[i]]]++;
        repp(i,1,up) cnt[i]+=cnt[i-1];
        for(int i=len-1;i>=0;i--) sa[--cnt[f[sr[i]]]]=sr[i];


        swap(f,r);
        p=0;
        f[sa[0]]=p++;
        rep(i,len-1)
        f[sa[i+1]]=(sa[i]+d<len && sa[i+1]+d<len && r[sa[i]+d]==r[sa[i+1]+d] && r[sa[i]]==r[sa[i+1]])?p-1:p++;
        d*=2;up=p;p=0;
    }
    rep(i,len) f[sa[i]]=i;
}
void getH(){
    int p=0;
    rep(i,len){
        if(f[i]==0) {height[f[i]]=0;continue;}

        int k=sa[f[i]-1];
        while(i+p<len && k+p<len && s[i+p]==s[k+p]) p++;
        height[f[i]]=p;
        p=max(0,p-1);
    }
}
int solve(int x){
    int l=1e9,r=0;
    int ans=0;
    repp(i,1,len){
        if(height[i]<x){
            if(r-l>=x) ans++;
            l=1e9;r=0;
        }else{
            l=min(l,min(sa[i],sa[i-1]));
            r=max(r,max(sa[i],sa[i-1]));
        }

    }
    if(r-l>=x) ans++;
    return ans;
}
int main(){
#ifndef ONLINE_JUDGE
  freopen("aaa","r",stdin);
#endif
    int T;
    while(~scanf("%s",s),s[0]!='#'){
         len=strlen(s);
         getSa();
         getH();
         long long ans=0;
         for(int i=1;i<=len/2;i++) ans+=solve(i);
         printf("%I64d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(hdu3518 后缀数组的height应用)