题解
- 有关子串循环的定理:假设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]。
- 根据上述定理,这里只需要求出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;
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)
cout<<'0'<<endl;
else
cout<<L-len%L<<endl;
}
return 0;
}