【kmp】【poj2406】Power Strings

本文介绍了一种使用KMP算法求解给定字符串最小循环节个数的方法。通过计算最长公共前后缀来确定最小循环节的长度,并提供了完整的C++实现代码。
  • 题意
    求给定串的最小循环节个数

  • 题解
    最小循环节长度=len-border
    border:最长公共前后缀
    kmp

  • 代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 1000001
using namespace std;
int nxt[MAXN];
char s[MAXN];
int main(){
    while(~scanf("%s",s+1)){
        if(s[1]=='.') break;
        int fix=0;
        int i;
        for(i=2;s[i];i++){
            while(fix&&s[fix+1]!=s[i]) fix=nxt[fix];
            if(s[fix+1]==s[i]) fix++;
            nxt[i]=fix;
        }
        i--;
        if((i-nxt[i])&&i%(i-nxt[i])==0)
            printf("%d\n",i/(i-nxt[i]));
        else
            printf("1\n");
    }
    return 0;
}
### 解题思路 Power Strings 问题是经典字符串算法题,目标是找出一个字符串 `s` 最多可以由多少个相同的子串 `a` 重复连接构成,即 `s = a^n`,其中 `n` 是要找的最大值。 解决此问题的关键是使用 **KMP(Knuth-Morris-Pratt)算法** 中的 `next` 数组,它能够帮助我们找出字符串中前后缀的最长匹配长度,从而判断字符串是否由某个子串重复多次构成。 #### KMP 中的 `next` 数组 在 KMP 算法中,`next[i]` 表示模式串从开头到第 `i` 位的子串中,最长的相等前缀与后缀的长度。利用这个特性,我们可以通过 `next` 数组来判断字符串是否存在重复子串。 设字符串长度为 `len`,如果 `len % (len - next[len]) == 0`,则说明字符串是由长度为 `len - next[len]` 的子串重复构成的,重复次数为 `len / (len - next[len])`。否则,无法由同一子串重复构成,返回 `1`。 --- ### 代码实现 以下为使用 KMP 算法求解 Power Strings 问题的实现代码: ```cpp #include <iostream> #include <cstring> using namespace std; const int MAXN = 1000005; char s[MAXN]; int next_arr[MAXN]; // 构建 next 数组 void build_next(int len) { next_arr[0] = -1; int j = -1; for (int i = 1; i < len; i++) { while (j >= 0 && s[i] != s[j + 1]) { j = next_arr[j]; } if (s[i] == s[j + 1]) { j++; } next_arr[i] = j; } } int main() { while (scanf("%s", s) != EOF && s[0] != '.') { int len = strlen(s); build_next(len); int repeat_len = len - next_arr[len - 1] - 1; if (len % repeat_len == 0) { printf("%d\n", len / repeat_len); } else { printf("1\n"); } } return 0; } ``` --- ### 示例分析 以 `ababab` 为例: - `len = 6` - `next[len - 1] = 3`,即最长前缀后缀匹配长度为 3。 - `repeat_len = len - next[len - 1] - 1 = 6 - 3 - 1 = 2` - `len % repeat_len == 0`,因此 `n = 6 / 2 = 3`,表示该字符串由 `"ab"` 重复 3 次构成。 对于 `aaaa`: - `len = 4` - `next[len - 1] = 3` - `repeat_len = 1` - `4 % 1 == 0`,因此 `n = 4` 对于 `abcd`: - `next[len - 1] = 0` - `repeat_len = 4 - 0 - 1 = 3` - `4 % 3 != 0`,因此 `n = 1` --- ### 时间复杂度分析 - 构建 `next` 数组的时间复杂度为 **O(n)**。 - 主函数中判断重复次数的时间复杂度为 **O(1)**。 - 总体时间复杂度为 **O(n)**,适用于最大长度为 1,000,000 的输入。 --- ### 优化与注意事项 - 输入规模较大,应使用 `scanf` 而非 `cin` 以避免超时。 - 需要处理多个测试用例,直到遇到输入为 `.` 的情况。 - 注意 `next` 数组构建时的索引处理,避免越界。 --- ### 总结 通过 KMP 算法中的 `next` 数组,可以高效判断字符串是否由某子串重复构成,并计算最大重复次数。该方法在时间复杂度和空间复杂度上都表现优异,适合处理大规模输入数据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值