字符串乘方(POJ NO.1408)

来源:互联网 发布:nba2k17mc捏脸数据 编辑:程序博客网 时间:2024/06/05 22:55

字符串乘方(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 1000010using 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算法的应用,值得一写。

  • 字符串乘方POJ NO1408
    • Question
    • My Hints
      • Algorithm
      • Codes


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