子串循环问题 (Ver. I)

题解
  1. 有关子串循环的定理:假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。
  2. 根据上述定理,这里只需要求出next[len]就可以了,所以不需要用KMP里面求next函数的方法,直接针对性的求next[len]。其中用到了字符串截取函数substr()。
题目
问题 J: 子串循环问题 (Ver. I)
时间限制: 1 Sec  内存限制: 128 MB
提交: 592  解决: 214
[提交][状态][讨论版]
题目描述
给定一个字符串,求需要添加至少几个字符到字符串末尾才能使得整个字符串串由某一个不为本身的子串循环构成?
如"abca",添加"bc"后构成"abcabc",其由子串"abc"循环构成;也可以添加"abca"后构成"abcaabca",其由子串"abca"循环构成,相比之下"bc"只有2个字符,添加的字符量最少。
输入
第一行包括一个整数T(1 <= T <= 100),代表测试组数

每组测试数据包括一行字符串,其长度范围为 [3, 104]

输出
对于每组测试数据

输出一个整数N,代表添加的最小字符数量

样例输入
3
aaa
abca
abcdefg
样例输出
0
2
7
代码块
#include <iostream>
#include <string>
using namespace std;

int GetNext(string a)
{
    string t1, t2;
    int len = a.length();
    int j = 0;//j记录相等时的最大长度
    for(int i=0; i<len-1; i++)
    {//长度由小到大
        t1 = a.substr(0, i+1);
        t2 = a.substr(len-1-i);
        if(t1==t2 && i+1>j)
            j = i+1;
    }
    return j;
}

int main(void)
{
    int i, n;
    cin>>n;
    for(i=0; i<n; i++)
    {
        string a;
        cin>>a;
        int len = a.length();
        int next_len = GetNext(a);
        int L = len-next_len;
        if(!(len%L) && len!=L)//这里要选择L整除len的情况,即len%L==0,但要注意要加个括号再取非,!符的优先级非常高。
        //根据题意,对于循环周期为1的串也需要补(即子串就是本身),所以L==len的情况要归到下面
            cout<<'0'<<endl;
        else
            cout<<L-len%L<<endl;
    }
    return 0;
}
  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值