2017.1.15【初中部 NOIP提高组】模拟赛B组 重复字符串(powerstr) 题解

原题:

http://172.16.0.132/senior/#contest/show/1899/2

题目描述:

给定两个字符串a和b,我们可以定义一些操作:a*b为将字符串a和字符串b连接起来,比如a= “aoe”,b= “jkw”,那么a*b= “aoejkw”。进一步,我们可以有指数操作,a^0= “”, a^1=a, a^2=a*a, a^n=a*(a^(n-1))=a*a*…*a (n个a)
现在给你一个字符串,你可以将它看成是a^n的形式,比如字符串”abababab”,可以认为是”abab”^2, 也可以是”abababab”^1,还可以是”ab”^4。
现在问题是,给定的字符串,我们想让它变成a^n中的n达到最大,那么这个n最大是多少?例如:”abababab”最大的n是4。

输入:

第一行,一个整数m,表示有m个字符串。
接下来m行每行输入一个只含小写字母的字符串。

输出:

输出m行,对于每行输出相应字符串的最大n。

样例输入:

3
abcde
aaaaaa
abababab

样例输出:

1
6
4

数据范围限制:

30%的数据:字符串的长度≤1000;
100%的数据:字符串的长度≤1000000, m≤10,字符串内只含小写字母。

分析:

假设字符串为 S,长度为 N,子串 T 重复 K 次后得到串 S,那么 T 的长度一定为 L = N/K(要整除),则 T = S[1…L],将 S 拆分成 K 份,每份长度为 L,则有S[1…L] = S[L+1…2L] = S[2L+1…3L] = … = S[(K-1)L+1…KL];由于要保证 K 最大,势必 L 要取最小,所以根据 Next 函数的定义,有 Next[KL] = (K-1)L;即 Next[N] = N - L,所以 L = N - Next[N];
但是得出的长度 L 还要保证能被 N 整除,所以如果不能整除说明 L = N,即 K = 1;而如果能整除,那么 K = N / (N - Next[N]);
因而我们只要对字符串 S 做一趟 KMP,对其求 Next 数组;

实现:

#include<cstdio>
#include<string>
#include<iostream>
using namespace std;

string s;
int i,j,n,m,ans,p,a[10007];
bool c(int x)
{
    int i,j;
    i=1;
    j=m/x;
    while(s[i]==s[i+j]&&i+j<m) i++;
    if(s[i]==s[i+j]) return true;
    else return false;
}
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        cin>>s;
        s='0'+s;
        m=s.length()-1;
        p=0;
        ans=1;
        for(j=2;j<=m;j++)
            if(m%j==0)
            {
                p++;
                a[p]=j;
            }
        for(j=p;j>=1;j--)
            if(c(a[j]))
            {
                ans=a[j];
                break;
            }
        printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值