-
题目描述:
-
给定一个由小写字母组成的字符串,求它的所有连续子串中,出现过至少两次,且至少有一对出现的重复子串是不重合的连续子串个数。
如给定字符串aaaa,aa和a,符合条件,aaa不符合条件(出现重合),故答案为2。
-
输入:
-
输入包含多组测试用例,每组测试用例包含一个字符串,由小写字母组成,其长度不大于1000。
-
输出:
-
对于每组测试数据,输出一个整数,代表符合条件的子串个数。
-
样例输入:
-
aaaa aaa
-
样例输出:
-
2 1
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
usingnamespace std;
constint MAX=2000;
chars[MAX];
intdp[MAX][20];
intsa[MAX],rank[MAX];
intbuc[MAX],sto[2][MAX];
charmod[MAX];
intr[MAX];
intLog[MAX];
inth[MAX];//sa[i],sa[i-1]最长公共前缀
boolcmp(int*y,inta,intb,intj)
{returny[a]==y[b]&&y[a+j]==y[b+j];}
//排序0-n,SA有用的是1-n,RANK有用的是0-n
//给定字符后面要加两个0,n传入实际长度
voidmake_suffix_arr(ints[],intn,intm)
{
int*x=sto[0],*y=sto[1],*t;
inti,j,p;
n++;
for(i=0;i<m;i++)buc[i]=0;
for(i=0;i<n;i++)buc[x[i]=s[i]]++;
for(i=1;i<m;i++)buc[i]+=buc[i-1];
for(i=n-1;i>=0;i--)sa[--buc[x[i]]]=i;
for(p=j=1;p<n;j<<=1,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++)buc[i]=0;
for(i=0;i<p;i++)buc[x[y[i]]]++;
for(i=1;i<m;i++)buc[i]+=buc[i-1];
for(i=n-1;i>=0;i--)sa[--buc[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++)
x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
}
}
voidcal_height(intn)
{
inti,k=0,j;
for(i=0;i<=n;i++)rank[sa[i]]=i;
for(h[i=0]=0;i<n;h[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
voidget_RMQ(intn)
{
inti,j;
inta,b;
for(i=0;i<=n;i++)
dp[i][0]=i;
for(j=1;(1<<j)<=n;j++)
for(i=1;i+(1<<j)-1<=n;i++)
{
a=dp[i][j-1];
b=dp[i+(1<<j>>1)][j-1];
if(h[a]<h[b])
dp[i][j]=a;
else
dp[i][j]=b;
}
}
intaskRMQ(intl,intr)
{
intt=Log[r-l+1];
inta=h[dp[l][t]],b=h[dp[r-(1<<t)+1][t]];
returna<b?a:b;
}
intlcp(inta,intb)
{
a=rank[a];
b=rank[b];
intt;
if(a>b)
{
t=a;
a=b;
b=t;
}
returnaskRMQ(a+1,b);
}
intcalc(intn,intlen)
{
inti,j;
intret=0;
for(i=0;i<=n;i++)
{
if(h[i]>=len)
{
intmin=sa[i-1],max=sa[i-1];
for(j=i;j<=n&&h[j]>=len;j++)
{
if(sa[j]>max)max=sa[j];
if(sa[j]<min)min=sa[j];
}
if(max-min>=len)ret++;
i=j-1;
}
}
returnret;
}
intmain()
{
inti;
Log[0]=-1;
for(i=1;i<MAX;i++)
Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1;
intn=100005;
while(scanf("%s",s)!=EOF)
{
n=strlen(s);
for(i=0;i<n;i++)r[i]=s[i];
r[n]=0;
make_suffix_arr(r,n,128);
cal_height(n);
//for(i=0;i<=n;i++)printf("%d\n",h[i]);
intret=0;
for(i=1;i*2<=n;i++)
{
ret+=calc(n,i);
}
printf("%d\n",ret);
}
return0;
}
/*
*/
/**************************************************************
Problem: 1555
User: 鬼M
Language: C++
Result: Accepted
Time:50 ms
Memory:1244 kb
****************************************************************/