POJ1961(KMP-Next数组)

不要想复杂

数组下标设为1开始

证明算法正确性:if + only if  充分+必要

输出格式,空行空格

特殊情况:全相等

数组作为参数传入函数   若指针传入,只传入第一个地址,不传长度,可用[]运算符,但不能strlen求长度。需单独传入长度length;或拷贝传入 char a[]

思路:

p[x]表示x长度的前缀的最短循环节的长度  aabaab,p[1]=0,p[2]=1,p[3]=3,p[6]=3

利用next数组,如果next[i]==i-1,则之前全相等,特例,p[i]=0;如果s[next[i]]==s[i] && i-next[i]==p[next[i]],next-i之前以及next-i到i之间均构成整数个循环节,next-i到i之间元素和循环节相等,则i的最小循环节长度和next-i的相等

i/next[i]=循环次数k

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
char s[1000000 + 10] = { 0 };
long long nex[1000000 + 10] = { 0 };
long long p[1000000 + 10] = { 0 };
void get_next(long long *na, char *sa, long long len) {
	long long j = 1, k = 0;
	na[1] = 0;
	while (j < len) {
		if (k == 0 || sa[k] == sa[j]) na[++j] = ++k;
		else k = na[k];
	}
}
void clear() {
	memset(s, 0, sizeof(s));
	memset(nex, 0, sizeof(nex));
	memset(p, 0, sizeof(p));
}
int main() {
	long long n, T = 1;
	cin >> n;
	while (n != 0) {
		string input;
		cin >> input;
		for (long long i = 1; i <= n; i++) {
			s[i] = input[i - 1];
		}
		get_next(nex, s, n);
		p[1] = 0;
		cout << "Test case #" << T++ << endl;
		for (long long i = 2; i <= n; i++) {
			if (nex[i] == i - 1) {
				if (s[i] == s[i - 1]) {
					p[i] = 0;
					cout << i << " " << i << endl;
				}
				else {
					p[i] = i;
				}
			}
			else if (s[nex[i]] == s[i]) {
				if (i - nex[i] == p[nex[i]]) {
					p[i] = p[nex[i]];
					cout << i << " " << i / p[i] << endl;
				}
				else p[i] = i;
			}
			else p[i] = i;
		}
		cout << "\n";
		cin >> n;
		clear();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值