[Ybt high-efficiency advanced 2-3-3] cycle length and

Period length and

Topic link: ybt efficient advanced 2-3-3

Topic

Give you a string and ask you to find the sum of the maximum period length of each prefix.
The cycle of a string is that it is a substring of it, but it cannot be an empty string or the string itself, and this substring is copied once to form a new string, which must contain the original string.

Ideas

In fact, it is to find a substring and copy it again to include the original string. For each substring, find the one with the largest length.

So we actually want to divide the original string into two parts, and then the former one contains the latter one. Then the cycle is the previous one.
Then let's see how to do it so that the previous one can include the latter one.
Let's think about KMP, it is KMP when we publish it.

Then we want to maximize the length of the period, that is, make the front as large as possible and the back as small as possible.
The length behind is actually the length of KMP, so we want to make this length as small as possible, that is to make KMP smaller?

That is actually to find the smallest that can match. That is constantly recursive faili fail_ifailiTo 0 00 , then tofaili = 0 fail_i=0faili=At 0 ,iii is the smallest.
Of course, we can use a similar idea of ​​union search to memorize, thereby reducing time.

Code

#include<cstdio>

using namespace std;

int n, j, fail[1000001];
long long ans;
char c[1000001];

int find(int now) {
    
    
	if (fail[now]) return fail[now] = find(fail[now]);
	return now;
}

int main() {
    
    
	scanf("%d", &n);
	scanf("%s", c + 1);
	
	j = 0;
	for (int i = 2; i <= n; i++) {
    
    //KMP
		while (j && c[i] != c[j + 1]) j = fail[j];
		if (c[i] == c[j + 1]) j++;
		fail[i] = j;
	}
	
	for (int i = 1; i <= n; i++) {
    
    
		ans += 1ll * i - 1ll * find(i);
	} 
	
	printf("%lld", ans);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/112978036