Topic links: Click here
Title effect: Given a string, asked how many substring occurs twice or more, the calculation can not overlap each other
Topic Analysis: Since the data range is relatively small, we can direct violence, enumerate substring length, using the height of the nature of the suffix array is divided into different groups, try to find the answer in each group to
Code:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=1e3+100;
char str[N];
int sa[N]; //SA数组,表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[N],t2[N],c[N];
int rk[N],height[N],len;
int s[N];
void build_sa(int s[],int n,int m)//n为添加0后的总长
{
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];
swap(x,y);
p=1,x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
if(p>=n)
break;
m=p;
}
}
void get_height(int s[],int n)//n为添加0后的总长
{
int i,j,k=0;
for(i=0;i<=n;i++)
rk[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k)
k--;
j=sa[rk[i]-1];
while(s[i+k]==s[j+k])
k++;
height[rk[i]]=k;
}
}
void solve(int base=128)
{
build_sa(s,len+1,base);
get_height(s,len);
}
int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);
while(scanf("%s",str)!=EOF&&str[0]!='#')
{
len=strlen(str);
for(int i=0;i<len;i++)
s[i]=str[i]-'a'+1;
s[len]=0;
solve(30);
int ans=0;
for(int i=1;i<=len/2;i++)
{
int mmax=-inf,mmin=inf;
for(int j=2;j<=len;j++)
{
if(height[j]>=i)
{
mmax=max(mmax,max(sa[j],sa[j-1]));
mmin=min(mmin,min(sa[j],sa[j-1]));
}
else
{
if(mmax-mmin>=i)
ans++;
mmax=-inf;
mmin=inf;
}
}
if(mmax-mmin>=i)
ans++;
}
printf("%d\n",ans);
}
return 0;
}