bzoj 1355 Radio Transmission

该博客讨论了如何找到一个不确定字符串的最短循环节长度。通过使用KMP算法,计算next[]数组,可以得出L-next[L]作为最小循环节的长度。博主详细解释了题意,并给出了解题思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给你一个字符串,它是由某个字符串不断自我连接形成的。 但是这个字符串是不确定的,现在只想知道它的最短长度是多少.

Input

第一行给出字符串的长度,1 < L ≤ 1,000,000. 第二行给出一个字符串,全由小写字母组成.

Output

输出最短的长度

Sample Input

8
cabcabca

Sample Output

3

HINT

对于样例,我们可以利用"abc"不断自我连接得到"abcabcabc",读入的cabcabca,是它的子串

题意分析

Hint中已经有解释,一个子串“abc”不断自我连接成“abcabcabc”,那么“cabcabca”也是它的一个子串,其中的“abc”是最小“循环节”,或者说“cab”是最小“循环节”

解题思路

这也是一个kmp的题目,对于给定的长度为L的字符串“cabcabca”计算出对应的next[]数组,那么L-next[L]就是最小循环节的长度,为什么呢?下面分析一下:

在这里插入图片描述

由上图可见,L=8,next[8]=5,最小循环节的长度= L-next[8] = 8-5 = 3,也就是“cab”的长度是3

为什么?
因为next[L]中存放的是这个字符串最大共同前后缀的长度(不包括整个串本身),这个值其实就是从第二个循环节开始一直到最后一个字符的长度,用整个字符串的长度 减去 这个值,得到的就是第一个循环节的长度。

举一个例子,假设一个循环节的长度为5,这个循环节经过多次重复(最后一次重复可能是不完整的)后得到一个字符串,我们这样表示:
12345 12345 12345 123
在这里,循环节“12345” 一共重复了4次,最后一次只有“123”,总长度L=18。
那么这个字符串,最大的后缀就是从第2次循环开始一直到最后一个字符:12345 12345 123;当然最大的前缀也是:12345 12345 123。所以用总长度减掉最大后缀长度 ,得到的就是第一个循环节的长度,也就是最小循环节的长度了。
在这里插入图片描述
这个最大后缀长度,正好是最后一个next值,即next[L]。
思路有了,代码就好办了,对于一个串,先计算出他的next[]值,然后用L-next[L]即可。

首先定义变量,因为题中说1 < L ≤ 1,000,000,所以定义一个字符数组s[1000010]
另外给他定义一个next数组 int next[1000010]
计算next数组的代码和以往一样,通过一个for循环和i、j来实现,
完整代码如下:

#include<cstdio>
#include<cstring>
char s[1000010];
int next[1000010];
int main()
{
    int i,j,len;
    scanf("%d%s",&len,s+1);
    for (i=2,j=0;i<=len;i++)
    {
        while (j&&s[i]!=s[j+1]) j=next[j];
        if (s[i]==s[j+1]) j++;
        next[i]=j;
    }
    printf("%d\n",len-next[len]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值