解题思路
——因为一个数组开小了调了1个小时,我无语了啊啊啊啊啊…TOT
这道题因为数据不大,可以直接跑
n
2
n^2
n2。
考虑枚举左端点,设左端点为
l
,
S
=
C
[
l
,
∣
C
∣
]
l,S=C[l,|C|]
l,S=C[l,∣C∣],那么对字符串S跑一次
K
M
P
KMP
KMP。
然后在统计过程中,假设现在在i位置,则
S
[
1
,
j
]
=
S
[
i
−
j
+
1
,
i
]
S[1,j]=S[i-j+1,i]
S[1,j]=S[i−j+1,i]。如果
j
∗
2
>
=
i
j*2>=i
j∗2>=i,那么令j=p[j],此时
A
[
1
,
j
]
=
a
[
i
−
j
+
1
,
i
]
,
j
A[1,j]=a[i-j+1,i],j
A[1,j]=a[i−j+1,i],j不断沿指针回跳,直到
j
∗
2
<
i
j*2<i
j∗2<i。然后再判断j是否大于等于k,如果是,那么累加答案。
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
char s[20010],c[20010];
int ans,j,k,l,len,m,p[20010];
int main() {
scanf("%s",c+1);
scanf("%d",&k);
len=strlen(c+1);
for(register int t=1; t<=len; t++) {
memset(s,0,sizeof(s));
memset(p,0,sizeof(p));
for(register int w=1;w+t-1<=len;w++)
s[w]=c[w+t-1]; //处理左端点
j=0,l=strlen(s+1);
for(register int i=2; i<=l; i++) {
while(j&&s[i]!=s[j+1])
j=p[j];
if(s[i]==s[j+1])
j++;
p[i]=j;
}
j=0;
for(register int i=1; i<=l; i++) {
while(j&&s[i]!=s[j+1])
j=p[j];
if(s[i]==s[j+1])
j++;
while((j<<1)>=i)j=p[j];
if(j>=k)ans++;
}
}
printf("%d",ans);
}