https://loj.ac/problem/10047
タイトル説明
文字列指定された\(S \)サブストリング満たすと判定され、\(ABA \)形式及び(| A |≧K \)\ \ (|≧1 \ | B)数。
考え
この問題は、まず明確にされている\(N ^ 2 \)暴力治療することができるが、定義されたタイトルに変換することができる(\)\共通接頭辞と接尾辞を超える長さのサブストリングである\(K \)全体サブ未満長さ\(\ FRAC。1} {2} {\) 、我々は考える(KMP \)\共通接頭辞と接尾辞を求め、その後、判断が暴力的なことができます。しかし、先にジャンプし続けることたびに、アカウントに裁判官を取って、残業の可能性がある、我々は、最適化を検討してください。まず、我々は明らかに列挙するために、各文字列の左端を列挙(NK * 2 \)\をそれに。次にため\(1- \シムN \)一度この期間\(KMP \) 。ため\(S [L ... R] \) このセクションでは、我々はプロセスを考える(P [I] = J \)\を、場合\(J <K-L 1 + \) 、次いで最長共通接頭辞と接尾辞は、満たされていない(=私は\ G [I])\、すなわちのみこの期間全体\(A \)文字列、そうでない場合に関連して、条件を満たし(G [J] \)\条件を、我々はそれ以降の状態にできるだけ短いので、ほとんど影響したいので。中間位置のかどうか、この項の判断の答え限り、最後に記録された位置。
コード
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e4+10;
char s[MAXN];
int pre[MAXN],n,g[MAXN];
int main()
{
int k;
scanf(" %s",s+1);
scanf("%d",&k);
n=strlen(s+1);
int ans=0;
for(int l=1;l<=n-(k<<1);l++)
{
pre[l]=l-1;
int j=l-1;
g[l]=l;
for(int p=l;p<n;p++)
{
while(j>l-1&&s[p+1]!=s[j+1])j=pre[j];
if(s[p+1]==s[j+1])j++;
pre[p+1]=j;
g[p+1]=(j<l+k-1)?p+1:g[j];
if(g[p+1]<(l+p+1)/2)
ans++;
}
}
printf("%d",ans);
return 0;
}