废话
又是热血沸腾的写了一发kmp,看完题目,蹦出个循环节,Emmm…
不是废话
结论:
设len=n−nxt[n]
(新理解:其实就是重叠的那个部分嘤嘤嘤
(1) nxt[n]=0 不存在循环节
(2) nxt[n]>0 && n%len≠0 存在循环节但是长度不整除
(3) nxt[n]>0 && n%len=0 存在整除循环节
而且更长的循环节一定是len的倍数。
刚刚又去写了一道题,咳咳,有了新的理解…
附上另一个题目(感觉差不多一样)的链接:KMP专题C题–循环节个数
题目
题目点我
题目意思呢就是给你一个字符串,求这个字符串到第i个字符为止的循环节的次数。
比如aabaabaabaab,长度为12.到第二个a时,a出现2次,输出2.到第二个b时,aab出现了2次,输出2.到第三个b时,aab出现3次,输出3.到第四个b时,aab出现4次,输出4.
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#define pb push_back
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
#define pq priority_queue
int n;
const int maxn = 1e6 + 5;
char s[maxn];
int next[maxn];
void get_next(char s[]){
int len = strlen(s);
next[0] = -1;
int i = 0, j = -1;
while(i != len){
if(j == -1 || s[i] == s[j]){
next[++i] = ++j;
}
else
j = next[j];
}
}
int main(){
int cnt = 0;
while(scanf("%d", &n) && n){
if(n == 0)
break;
scanf("%s", s);
get_next(s);
printf("Test case #%d\n", ++cnt);
int len = 0;
for(int i = 1; i <= n; i++){
len = i - next[i];
if(i != len && (i % len == 0)){
printf("%d %d\n", i, i / len);
}
}
printf("\n");
}
return 0;
}