字符串乘方(POJ NO.1408)

本文介绍了一道经典的字符串问题——字符串乘方(POJ NO.1408),并提供了详细的KMP算法实现过程。通过分析输入字符串s的最大重复次数n,使得s可表示为某个字符串a的n次幂。

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

字符串乘方(POJ NO.1408)

总时间限制: 3000ms
内存限制: 65536kB

Question

描述
给定两个字符串a和b,我们定义a*b为他们的连接。例如,如果a=”abc” 而b=”def”, 则a*b=”abcdef”。 如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a^0=””(空字符串),a^(n+1)=a*(a^n)。

输入
每一个测试样例是一行可打印的字符作为输入,用s表示。s的长度至少为1,且不会超过一百万。最后的测试样例后面将是一个点号作为一行。

输出
对于每一个s,你应该打印最大的n,使得存在一个a,让s=a^n

样例输入

abcd
aaaa
ababab
.

样例输出

1
4
3

提示

本问题输入量很大,请用scanf代替cin,从而避免超时。

来源

Waterloo local 2002.07.01

My Hints

Algorithm

看到题目的提示说用scanf代替cin,于是我一开始查阅Artificial Intelligence的博客后,选择了sscanf(str, “%[^.]”, string) ; 输出依旧使用cout,调试时发现无法输出,只能改为printf才能够输出。但当我输入样例时发生错误,捣鼓了半天,不得已之下做了“[小林丸号]1(Kobayashi Maru)式处理”:
将输入改为cin >> str && str != "." ,为减少超时可能,我们先关闭流同步:std::ios_base::sync_with_stdio(false); (当然也可以将str定义为char类型的字符数组,利用scanf输入比定义为string类型的输入会更通用一些scanf("%s",c)&&c[0]!='.')从而加快cin的输入速度。此时输入正常。可进行KMP算法的编写。

KMP算法在姚光超的专栏讲解得十分清楚,推荐大家去看,这里不再赘述。

由于我们规定fail数组下标从1开始,故将str前加空格与Fail数组一致。利用KMP算法更新fail数组之后,用 lenfail[len] 即可得到最小循环节。若总长不能整除最小循环节长度,则无循环节,即循环节为其本身;否则循环节为总长除以最小循环节长度。

Codes

代码主要思想参考getsum的博客


@ hzhang_97@foxmail.com
// Author: Florence
// Created Time: 2017-08-18 09:37:30

#include <iostream>
#include <cstring>
#define max_n 1000010
using namespace std;

string str;
int fail[max_n];
int i,j,len,loop;

int main(int argc, char** argv) {
    std::ios_base::sync_with_stdio(false);//关闭流同步,从而加快cin的输入速度 

    while (cin >> str && str != "."){
        memset(fail,0,sizeof(fail));//每组数据均应初始化 
        len = str.length();
        str = " " + str;//由于我们规定Fail数组下标从1开始,故将str前加空格与fail数组一致 
        j = 0;

        //利用KMP算法更新fail数组 
        for (i = 2;i <= len;i++){
            while (j > 0 && str[j+1] != str[i]) j = fail[j];
            if (str[j+1] == str[i]) j++;
            fail[i] = j;
        }

        loop = len - fail[len];//得到最小循环节 

        //若总长不能整除最小循环节长度,则无循环节,即循环节为其本身 
        if (len % loop) printf("%d\n",1);
        //否则循环节为总长除以最小循环节长度 
        else printf("%d\n",len / loop);
    }
    return 0;
}

此题考查KMP算法的应用,值得一写。


  1. 星舰学院中著名的“小林丸”测试:学员模拟指挥的星舰,接到位于中立地带“小林丸”号运输舰发出的求救信号,而后,根据星际舰队(starfleet)的规定,星舰必须前往营救。在营救行动即将开始的时候,会有三艘克林贡战船解除隐形,进而无理由的攻击星舰。该测试是一个不可能完成的任务。它测试的目的是:通过不可能完成的任务,锻炼学员承受压力的能力,并能够使其坦然面对最后的时刻。当电影临近结束时,我们发现柯克船长更改了模拟训练装置,使它实际上可以获胜。柯克非常聪明,但他并没有解决小林丸号的困境,只是避开了它而已。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值