【Openjudge】前缀中的周期

运用kmp中的next数组。

前缀中如果有周期的话,一定满足,next[i] % (i - next[i]) == 0.

满足这个条件时:

记字符串s的第i位之前的子串为p,其前缀字符串位为p.pre,后缀字符串为p.suf,以p(i,j)表示p的从i位到j - 1的字串。则i就是p的长度,next[i] 就是p.pre和p.suf的长度.

首先知道,p.pre(0,i - next[i]) = p(0, i - next[i]),因为这俩就是p的同一个子串。

又有p.pre = p.suf,所以有,p.pre(0,i - next[i]) = p.suf(0, i - next[i]).

而p.suf(0,i - next[i]) = p(i - next[i],(i - next[i]) * 2) = p.pre(i - next[i], (i - next[i]) * 2);

以此类推,可以发现p是由,p除去p.suf的子串为周期的,周期字符串。

#include<iostream>
#include<string>
using namespace std;

#define MAXN 10010000

int* cmput(int *const next, const string &s){
	int ls = s.length();
	int i = 0, j = -1;
	next[0] = -1;
	while (i < ls){
		while (j >= 0 && s[i] != s[j]){
			j = next[j];
		}
		i ++;
		j ++;
		next[i] = j;
	}
	return next;
}

int main(){
	int n;
	string s;
	int *next = new int[MAXN];
	int l;
	int count = 1;
	while(cin >> n){
		if (!n)
			return 0;
		cout << "Test case #" << count++ << endl;
		cin >> s;
		l = s.length();
		cmput(next, s);

		for (int i = 2; i <= l; i ++){
			if (next[i] == 0)
				continue;
			if (next[i] % (i - next[i]) == 0){
				cout << i << ' ' << i / (i - next[i]) << endl;
			}
		}
		cout << endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值