>Link
ybtoj子串拆分
>Description
已知一个字符串 ,求它有多少个形如 A+B+A 的子串( len(A)≥k,len(B)≥q )。
位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一子串。
1 ≤ ∣ S ∣ ≤ 15000 1≤|S|≤15000 1≤∣S∣≤15000
>解题思路
看到这个数据范围, O ( n 2 ) O(n^2) O(n2)是可以过的
然后我们就先 O ( n ) O(n) O(n)找一个左端点 l l l,跑一遍以 l l l为起点的KMP,然后在暴力枚举右端点,看看以右端点为结尾的nxt有无符合题目条件的,累计答案
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 15010
using namespace std;
int n, k, nxt[N], ans;
string s;
int main()
{
cin >> s;
scanf ("%d", &k);
n = s.size(); s = " " + s;
for (int l = 1; l <= n - 2 * k; l++)
{
memset (nxt, 0, sizeof (nxt));
for (int i = 2, j = 0; i <= n - l + 1; i++)
{
while (j && s[l + j] != s[l - 1 + i])
j = nxt[j];
if (s[l + j] == s[l - 1 + i]) j++;
nxt[i] = j;
}
for (int i = 2, j = 0; i <= n - l + 1; i++)
{
while (j && s[l + j] != s[l - 1 + i])
j = nxt[j];
if (s[l + j] == s[l - 1 + i]) j++;
while (j * 2 >= i) j = nxt[j];
if (j >= k) ans++;
}
}
printf ("%d", ans);
return 0;
}