HDU-3746
现在给你一个字符串,请问在该字符串末尾最少添加多少个字符,可以让这个字符串获得重复循环序列。
输入:第一行是一个整数 代表测试数据的组数。之后 行每行一个字符串,由小写字母组成,字符串的长度 。
输出:每组数据输出一行结果。
样例:
3
ppp
pip
machinelearning
0
1
15
思路:
循环节是指一段数据中重复的最小环。KMP不止要学会套模板匹配字符串,还要学到KMP算法的精髓——Next数组。
(未经优化的)
指的
的最大共同前后缀长度(例如abcabcabc的共同前后缀为abcabc, abcabc为abc, abcabcabcabc为abc*3)
故一段字符串的循环节就是:
将其记为len。若该字符串是循环字符串,则
, 而循环节的个数为:
若不是,则
(abcd)或者
题解:
#include<bits/stdc++.h>
#define maxn 1000005
using namespace std;
int n;
char s[maxn];
int Next[maxm];
int getnext()
{
Next[0] = -1;
int i = 0, j = -1;
while(i<n)
{
while(j!=-1 && s[i]!=s[j]) j = Next[j];
Next[++i] = ++j;
}
int len = - Next[n] + n;
if(Next[n]==0) return len; //没有循环部分,只能自身成为循环节
else if(Next[n]%len==0) return 0; //已经是循环字符串
else return len - Next[n] % len; //需要补齐
}
int main()
{
int T;
cin >> T;
getchar();
while(T--)
{
scanf("%s", s);
n = strlen(s);
cout << getnext() << endl;
}
return 0;
}
HDU-1385
给出一个字符串s(1为起始),问在[1, i]区间是否有完整的循环节,若有,输出i并输出循环次数
3
aaa
12
aabaabaabaab
0
Test case #1
2 2
3 3
Test case #2
2 2 --aa(a)
6 2 --aabaab(aab)
9 3 --aabaabaab(aab)
12 4 --....
思路:求出Next数组后从1开始遍历,若 是循环字符串则输出 和
题解:
#include<bits/stdc++.h>
#define maxn 1000005
using namespace std;
int N, kase=0;
char s[maxn];
int Next[maxn];
void getnext()
{
Next[0] = -1;
int i = 0, j = -1;
while(i<N)
{
while(j!=-1 && s[i]!=s[j]) j = Next[j];
Next[++i] = ++j;
}
printf("Test case #%d\n", ++kase);
for(int i=2;i<=N;i++)
{
if(Next[i]==0) continue;
int len = i - Next[i];
if(Next[i]%len==0) cout << i << ' ' << Next[i]/len+1 << endl;
}
putchar('\n');
}
int main()
{
scanf("%d", &N); getchar();
while(N)
{
gets(s);
getnext();
scanf("%d", &N); getchar();
}
return 0;
}
HUST-1010
对于字符串A, 将其重复多次,形成新的字符串AAA…AAAA,在其中截取一段,作为B.
现给定B字符串,求符合条件的最短的A
扫描二维码关注公众号,回复:
9220986 查看本文章
bcabcab
efgabcdefgabcde
3
7
思路:本题实际上就是在求B中的循环节长度,只不过前/后可以多/少一些部分,原来的方法依然是可求的。
代码略