POJ1961(KMP-Next数组)

来源:互联网 发布:邵长文免费算命软件 编辑:程序博客网 时间:2024/05/29 18:28

不要想复杂

数组下标设为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
原创粉丝点击