1961 Period //KMP

Period
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 6003 Accepted: 2548

Description

For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K ,that is A concatenated K times, for some string A. Of course, we also want to know the period K.

Input

The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line contains the string S. The input file ends with a line, having the
number zero on it.

Output

For each test case, output "Test case #" and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.

Sample Input

3
aaa
12
aabaabaabaab
0

Sample Output

Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

Source

 

 

#include<stdio.h>

char s[1000001];

int p[1000001],n;

void init()

{

    int j;

    p[1]=0;

    for(int i=2;i<=n;i++)

    {

        j=p[i-1];

        while(j>0&&s[j+1]!=s[i])  j=p[j];

        if(s[j+1]==s[i])  j++;

        p[i]=j;

    }

}

int main()

{

    int cas=1;

    while(scanf("%d",&n)!=EOF)

    {

        if(n==0)  break;

        printf("Test case #%d/n",cas++);

        scanf("%s",s+1);

        init();

        for(int i=2;i<=n;i++)

        {

            if(i%(i-p[i])==0&&i/(i-p[i])!=1)  printf("%d %d/n",i,i/(i-p[i]));

        }

        printf("/n");

    }

    return 0;

}

<think>嗯,用户问的是KMP算法中的周期概念及其应用。首先,我需要回忆一下KMP算法的基本结构和next数组的作用。KMP算法主要用于字符串匹配,其核心是通过next数组避免回溯,提高匹配效率。而周期这个概念可能和字符串的重复模式有关。 根据引用中的资料,特别是引用[4]提到,字符串的周期Q是proper前缀,且原字符串是Q+Q的前缀。这说明周期是指字符串可以由某个子串重复多次构成。例如,像“abcabcabc”这样的字符串,周期Q是“abc”,重复三次。 接下来,next数组如何与周期相关联呢?引用[1]、[3]、[5]都提到next数组可以用于判断周期性。比如引用[3]中的例子,当next数组的值满足特定条件时,可能存在周期性。例如,若字符串长度n减去next[n]的值d能够整除n,那么d就是周期长度。 需要解释清楚周期在KMP中的具体定义,以及如何通过next数组来判断。用户可能想知道为什么next数组能反映周期性,这里需要结合next数组的计算过程来说明。每次计算next[i]时,寻找的是最长相同前后缀,如果字符串有周期性,那么最长前后缀可能会有一定的重复模式。 然后,应用方面,引用[1]提到判断字符串前缀的周期性,这在处理重复模式的问题时非常有用,比如数据压缩或模式识别。需要举一个具体的例子,比如字符串“abcabcab”,其next数组最后一个值是6,n=9,所以周期长度是9-6=3,即“abc”。 可能用户还希望了解如何实际应用这一特性,比如在算法题中判断字符串是否有周期,或者利用周期性优化某些操作。需要确保解释清晰,并引用相关的参考资料来支持论点。 另外,要注意用户可能对proper前缀的概念不熟悉,需要简要解释:proper前缀是指长度小于原字符串的前缀。这有助于理解周期的定义。 最后,总结周期在KMP中的应用场景,强调通过next数组高效判断周期性,避免重复计算,提升算法效率。同时,结合引用中的例子,确保回答准确且有依据。</think>### KMP算法中的周期概念及应用 #### 1. **周期定义** 在KMP算法中,字符串$S$的**周期**指满足以下条件的子串$Q$: - $Q$是$S$的一个**proper前缀**(即长度小于$S$的前缀); - $S$是$Q$与自身多次连接后的前缀。例如,若$S=abcabcab$,则周期$Q=abc$,因为$S$是$Q$重复3次($abc+abc+abc$)的前缀[^4]。 数学表达为:若字符串长度为$n$,周期长度为$d$,则需满足$d \mid (n - d)$且$S[1 \sim n-d] = S[d+1 \sim n]$[^3]。 #### 2. **周期与next数组的关系** KMP算法中的`next`数组记录了字符串每个位置的最长相同前缀和后缀的长度。通过`next`数组可以快速判断周期性: - **周期长度计算**:若字符串长度为$n$,且$n - next[n]$(记为$d$)能整除$n$,则$d$为周期长度。 - **验证条件**:周期子串需满足$S[1 \sim d] = S[d+1 \sim 2d] = \cdots$[^1]。 **示例**: 字符串$S=abcabcab$,其`next[8]=5`,计算周期长度$d=8-5=3$。验证发现$S[1\sim3]=abc$,$S[4\sim6]=abc$,$S[7\sim8]=ab$,因此周期为$abc$。 #### 3. **应用场景** 1. **模式匹配优化**:通过周期性跳过重复匹配,减少比较次数[^2]。 2. **数据压缩**:利用周期性将重复子串编码为更短的形式。 3. **算法题常见问题**:例如判断字符串是否由某子串重复多次构成(LeetCode 459题)。 #### 4. **代码实现示例** 通过`next`数组判断周期性的核心逻辑: ```python def has_period(s): n = len(s) next_array = [0] * (n + 1) j = 0 for i in range(1, n): while j > 0 and s[i] != s[j]: j = next_array[j] if s[i] == s[j]: j += 1 next_array[i + 1] = j d = n - next_array[n] return d != n and n % d == 0 # 判断是否为有效周期 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值