求给定字符串中有多少个不可重叠的重复子串。
和POJ 1743差不多,只不过那个是判定性问题可以二分求解。这个是找出来所有,那么直接枚举所有可能长度...
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
#define N 2012
int sa[N],ra[N],height[N];
int t1[N],t2[N],c[N],s[N];
char a[N];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void getsa(int n,int m)
{
int i,j,p,*x=t1,*y=t2;
for(i=0; i<m; i++) c[i]=0;
for(i=0; i<n; i++) c[x[i]=s[i]]++;
for(i=1; i<m; i++) c[i]+=c[i-1];
for(i=n-1; i>=0; i--) sa[--c[x[i]]]=i;
for(j=1; j<=n; j<<=1)
{
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++)c[i]=0;
for(i=0; i<n; i++)c[x[y[i]]]++;
for(i=1; i<m; i++)c[i]+=c[i-1];
for(i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
if(p>=n)break;
m=p;
}
}
void getheight(int n)
{
int i,j,k=0;
for(i=1; i<=n; i++) ra[sa[i]]=i;
for(i=0; i<n; i++)
{
if(k) k--;
j=sa[ra[i]-1];
while(s[i+k]==s[j+k]) k++;
height[ra[i]]=k;
}
}
int OK(int len,int i)
{
int ans=0;
int MAX=-1,MIN=1002;
for(int j=1; j<=len; j++)
{
if(height[j]>=i)
{
MAX=max(max(sa[j-1],sa[j]),MAX);
MIN=min(min(sa[j-1],sa[j]),MIN);
}
else
{
if(MAX-MIN>=i) ans++;
MAX=-1;
MIN=1002;
}
}
if(MAX-MIN>=i) ans++;
return ans;
}
int main()
{
char x[1234];
while(scanf("%s",x),strcmp(x,"#")!=0)
{
int len=strlen(x);
for(int i=0; i<len; i++)
s[i]=x[i]-'a'+2;
s[len]=0;
getsa(len+1,30);
getheight(len);
int ans=0;
for(int i=1; i<len; i++)
ans+=OK(len,i);
printf("%d\n",ans);
}
return 0;
}