循环节问题包括 完全循环 和 不完全循环
完全循环
对于一个具有循环节并且长为n的字符串,其循环节长为 n - n x t [ n - 1 ] ,并且满足n % ( n - n x t [ n - 1 ] ) ==0 , 这里nxt [ ]是KMP算法中的next 数组,并且是对于本博客上上上篇给出的KMP模板的方法构造nxt数组来说的。
本篇博客KMP算法的讲解在这里:KMP板子
(不同的构造方法可能式子不一样,比如有的方法下可能是 n - n x t [ n ] )
不完全循环
不完全循环是说需要补上一些位才能构成完整的循环,比如abca,就可以称为一个不完全循环,需要补上bc才能构成一个完整的循环。而完全循环则是类似abcabc这样的。设字符串长度为 len ,那循环节长度就是 len-nxt [len-1],需要补全的位数就是循环节长度-nxt [ len-1 ]%循环节长度。
证明
其实写出一个字符串模拟一下就能感觉到。
比如给出字符串:abcdabcdabcd,长度为12,而我们 nxt [ 12-1 ] = nxt [ 11 ] = 8,根据这个nxt数组的定义,它表示的是这个字符串前缀和后缀相等的最大长度,如果是完全循环,那么剩下的也就是 len-nxt [ 11 ]当然就是最大的循环节长度了。
如果把字符串改为:abcdefabc,我们可以知道,循环节算的方法跟完全循环的一样,就是len - nxt [ len-1 ]=L,即abcdef,那么 nxt [ len-1 ] 就是最后剩下的一串字符,它可能大于循环节也可能小于循环节(大于循环节的时候:len - nxt [ len-1 ] < nxt [ len-1 ],即 2 * nxt [ len-1 ] > len,比如azaza的情况)因此我们要用nxt [len-1] %循环节长度表示剩下的,而需要补全的当然就是循环节长度减去这个值啦。
下面是例题:
完全循环
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1000005
using namespace std;
char s[maxn];
int nxt[maxn];
int n;
void build()//构造nxt表
{
int k=0;
nxt[0]=0;
for(int i=1;i<n;i++)
{
while(k&&s[i]!=s[k])
k=nxt[k-1];
if(s[i]==s[k])
k++;
nxt[i]=k;
}
}
int main(void)
{
int kase=0;
while(~scanf("%d",&n)&&n)
{
memset(nxt,0,sizeof(nxt));
scanf("%s",s);
build();
printf("Test case #%d\n",++kase);
for(int i=1;i<n;i++)
{
int len=i+1;
int mid=len%(len-nxt[len-1]);//求出循环节长度
if(mid==0&&nxt[len-1]!=0)
{
int res=len/(len-nxt[len-1]);
printf("%d %d\n",len,res);
}
}
printf("\n");
}
return 0;
}
不完全循环
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 100005
using namespace std;
char s[maxn];
int nxt[maxn];
int n;
void build()
{
int k=0;
nxt[0]=0;
for(int i=1;i<n;i++)
{
while(k&&s[i]!=s[k])
k=nxt[k-1];
if(s[i]==s[k])
k++;
nxt[i]=k;
}
}
int main(void)
{
int t;
int ans;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
n=strlen(s);
build();
int mid=n-nxt[n-1];//要循环多少
if(mid!=n&&n%mid==0)
printf("0\n");
else
printf("%d\n",mid-nxt[n-1]%mid);
}
return 0;
}
-------------------------这样以后--------------------------------基本上都是-------------------------------------板子------------------------------------了
呼呼