【ybt高效进阶2-3-3】周期长度和

该博客探讨了一种利用KMP算法求解字符串每个前缀的最大周期长度之和的问题。通过KMP预处理得到部分匹配表,并寻找能让前缀尽可能大、后缀尽可能小的子串,以最大化周期长度。博主给出了代码实现,并提到了使用类似并查集的思想进行记忆化以优化时间复杂度。
摘要由CSDN通过智能技术生成

周期长度和

题目链接:ybt高效进阶2-3-3

题目大意

给你一个串,要你求每个前缀的最大周期长度之和。
一个串的周期就是它是它的一个子串,但是不能是空串也不不能这个串本身,而且这个子串复制一遍之后形成一个新的字符串,这个新的字符串要包含原来的串。

思路

其实就是要找一个子串,复制一遍之后包含了原来串。对于每个子串倒要找长度最大的那个。

那我们其实就是要让原来的串分成两份,然后前面的那个包含后面的那个。然后周期就是前面的那个。
那我们看看怎样搞,才能让前面的包含后面的那个。
我们跟 KMP 联想一下,发下它就是 KMP。

那我们要让周期长度最大,就是要让前面的尽可能大,后面的尽可能小。
那后面的长度其实就是 KMP 的长度,那我们要让这个长度尽可能小,那就是要 KMP 更小?

那其实是要找到能匹配的最小的。那就是不断得递归 f a i l i fail_i faili 0 0 0,然后到 f a i l i = 0 fail_i=0 faili=0 的时候, i i i 就是最小的。
当然我们可以用类似并查集的思想来进行记忆化,从而减少时间。

代码

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值