子串拆分【KMP】【暴力】

>Link

ybtoj子串拆分


>Description

已知一个字符串 ,求它有多少个形如 A+B+A 的子串( len(A)≥k,len(B)≥q )。
位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一子串。

1 ≤ ∣ S ∣ ≤ 15000 1≤|S|≤15000 1S15000


>解题思路

看到这个数据范围, 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;
}

Guess you like

Origin blog.csdn.net/qq_43010386/article/details/120947971