SCAU18940--最小循环节(kmp)

18940 最小循环节(KMP算法)

时间限制:1000MS  代码长度限制:10KB
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC;JAVA;PYTHON

Description

给定一个字符串,请计算这个字符串最多是由多少个相同的子字符串重复连接而成的。
如:acacac 最多有 3 个 ac 连接而成,bbbb最多由4个b连接而成,abc最多由1个abc连接而成。

此问题需求出整个字符串的最大相同真前后缀,需使用kmp算法或字符串哈希法,具体解释可看下图或百度最小循环节。

输入格式

一个字符串,长度不超过100000。


 

输出格式

组成字符串的最多重复连接子串的个数。


 

输入样例

ababab


 

输出样例

3

按照之前使用的next值计算技巧可知(之前的那篇计算的next值输出时,题目要求是错位输出):
计算的是最长前后缀相同的长度

ababab的为:001234

 再看几个例子:

字符串pi数组len周期 p = n - len可重复次数
ababab0 0 1 2 3 446 - 4 = 23
bbbb0 1 2 334 - 3 = 14
abcabcab0 0 0 1 2 3 448 - 4 = 42
abcde0 0 0 0 005 - 0 = 51

我们来看一下:

s = a b a b a b
              ↑
   这个位置是 len = 4,也就是 abab

s 的结构是:
头部:a b a b
尾部:    a b a b

你发现了吗?

  • 这说明这个字符串前面一部分和后面一部分是重复的

  • 所以它的结构很可能是某个短的字符串反复重复而成


第三步:周期的真正含义

我们现在来观察一个假设:

设字符串有周期 p,如果:

s[0] == s[p]
s[1] == s[p+1]
s[2] == s[p+2]
...

这样不断循环重复,直到构成整个字符串 ⇒ 就叫它是一个周期。

ababab 中,我们尝试看看周期长度为 2 是否成立?

周期单位: ab 重复 3 次: ab ab ab

 恰好等于字符串 ⇒ 周期成立!


第四步:为什么周期 = n - len?

我们知道:

  • 最长相同的前后缀长度是 len

  • 如果你把这部分“挖掉”,只剩中间的那个基本单元

  • 也就是说周期 = 整个长度 - 匹配的前后缀长度 ⇒ 周期 = n - len

ababab 中:

n = 6
len = 4
周期 p = 6 - 4 = 2

s[0..1] = ab,就是周期单元
ababab = ab + ab + ab

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main() {
    string s;
    cin >> s;
    int n = s.size();
    vector<int> pi(n);
    
    // 构造前缀函数(KMP的next数组)
    for (int i = 1; i < n; i++) {
        int j = pi[i - 1];
        while (j > 0 && s[i] != s[j]) {
            j = pi[j - 1];
        }
        if (s[i] == s[j]) {
            j++;
        }
        pi[i] = j;
    }

    // 获取最后一个位置的pi值
    int len = pi[n - 1];
    int period = n - len;

    // 判断是否可以整除
    if (n % period == 0) {
        cout << n / period << endl;
    } else {
        cout << 1 << endl;  // 不能整除则只能重复1次
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值