最短周期子串出现次数
想要知道最短周期子串出现的次数,首先要知道最短周期子串是什么,之后由目标串的长度/最短循环子串的长度就可以得到最短周期子串出现的次数.
假设有一个目标串为:abcabcabc
显而易见:最短周期子串为abc
一是暴力查找
代码如下
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
int min = 1;
cin >> str;
for (int i = 0; str[i] != '\0'; i++)
for (int z = 0; z + min < str.length(); z++)
if (str[z % min] != str[z + min]) {
min++;
break;
}
if (str.length() % min != 0) //防止出现输入"abcab"却输出3的情况`在这里插入一段代码
cout << str.length() << endl;
else
cout << min << endl;
return 0;
}
另一种是借用KMP算法中的next数组实现
上述目标串的next数组为
目标串 | a | b | c | a | b | c | a | b | c | ‘\0’ |
---|---|---|---|---|---|---|---|---|---|---|
next数组 | -1 | 0 | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
记目标串总长度为n,由表格可知n=9,next[9]=6,说明目标串中的第9个元素已经与前面连续重复了6个字符,也就是从字符串的第n-next[9]=3个字符处开始重复,所以子串长度为3.
-
另外举两个例子:
- 一个是:
目标串 a b c a b c a b ‘\0’ next数组 -1 0 0 0 1 2 3 4 5 这里就会发现n-next[n]=8-next[8]=3,但是实际上n=8,因为最后一个字符串没有字符’c’导致没有完成一个完整的循环,那么我们就需要判定,判定条件也很简单:目标串是由字符串循环得到的,所以判定条件
(目标串的长度%循环子串的长度)==0
应该为真,否则一个目标串的最长循环子串就是他自身.这样一来,这里先判定出n-next[n]=8-next[8]=3,然后判定(8%3)==0,为假,所以最短循环子串是目标串自身
-
另一个是
目标串 a b c a b c a b c d ‘\0’ next数组 -1 0 0 0 1 2 3 4 5 6 0 依然按照上述操作,n-next[n]=10-0=10,之后判断(10%10)==0,成立,所以最小周期子串的长度为10,也就是它自身.
代码如下:
#include<stdio.h>
#include<string.h>
int next[1000005]={0};
char T[1000005];
int getnext(char* T){
next[0]=-1;
int n=strlen(T);
int i=0,j=-1;
while(i<=n){
if(j==-1||T[i]==T[j]){
++j;
++i;
next[i]=j;
}
else{
j=next[j];
}
}
if(n%(n-next[n])==0)
return n/(n-next[n]);
else{
return 1;
}
}
int main(){
while(1){
int min=0;
scanf("%s",T);
if(T[0]=='.'){
return 0;
}
int cc=getnext(T);
int n=strlen(T);
printf("%d\n",cc);
}
return 0;
}