kmp算法
Posted downrainsun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kmp算法相关的知识,希望对你有一定的参考价值。
https://blog.csdn.net/dl962454/article/details/79910744
https://blog.csdn.net/qq_40938077/article/details/80460853
https://blog.csdn.net/liujiuxiaoshitou/article/details/70232219
https://vjudge.net/contest/240809#problem/A习题链接
Number Sequence
//这道题的next数组是由优化的next数组写的,next数组的含义不是指最长前缀与后缀的长度,因为加了递归优化,值一般就是-1与0.
//求最开始的匹配位置。(题目意思)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxm = 1e6 + 5; int a[maxm], b[maxm], nex[maxm]; int t, n, m, x; void getnext() { nex[0] = -1; int k = -1; int j = 0 ; while(j < m - 1) { if(k == -1 || b[j] == b[k]) { j++, k++; if(b[j] != b[k]) nex[j] = k; else nex[j] = nex[k]; } else k = nex[k]; } } int kmps() { int i = 0, j = 0; getnext(); while(i < n && j < m) { if(j == -1 || a[i] == b[j]) { i++, j++; } else j = nex[j]; // printf("cbuisdc "); } if(j == m) return i - j + 1; return -1; } int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); } for(int i = 0; i < m; i++) { scanf("%d", &b[i]); } if(kmps() == -1) printf("-1 "); else printf("%d ", kmps()); } return 0; }
Period
从这一题把next数组输出可知,next数组值该字符串的最长相同前缀与后缀,而且是包含了本身的。(如果这么说的话,相当于把字符串下标从1开始)
//这个是没加递归优化的next数组,指的是最长前缀与后缀的值。
//题目意思是指在i之前的字符串是不是有循环节的,有的话就输出循环节的长度与循环节的个数。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxm = 1e6 + 5; int n; int nex[maxm]; void getnext(char ch[], int m) { memset(nex, 0, sizeof(nex)); nex[0] = -1; int j = 0, k = -1; while(j < m) { if(k == -1 || ch[j] == ch[k]) { j++; k++; nex[j] = k; } else k = nex[k]; } //for(int i = 0; i <= m; i++) { // printf("%d ", nex[i]); //} //printf(" "); } char ch[maxm]; int main() { int cnt = 0; while(~scanf("%d", &n) && n) { scanf("%s", ch); getnext(ch, n); printf("Test case #%d ", ++cnt); for(int i = 2; i <= n; i++) { int j = i - nex[i]; if(j != i) { if(i % j == 0) { printf("%d %d ", i, i / j); } } } printf(" "); } return 0; }
Simpsons’ Hidden Talents
//这个nex数组是用的最长前缀与后缀,题目意思是指求两个字符串的最长相同的前缀与后缀。
//这个在kmp匹配那里有不同,重点看一下。还有一种做法是直接把两个字符串拼接起来,在中间加一个特殊字符,然后在用kmp去求最长前缀与后缀的长度。
/* @Author: Top_Spirit @Language: C++ */ //#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std ; typedef unsigned long long ull ; typedef long long ll ; const int Maxn = 5e4 + 10 ; const int INF = 0x3f3f3f3f ; const double PI = acos(-1.0) ; const ull seed = 133 ; string s1, s2 ; int len1, len2 ; int Next[Maxn] ; void getNext(){ Next[0] = -1 ; int j =0, k = -1 ; while (j < len1 ){ if (k == -1 || s1[j] == s1[k]) Next[++j] = ++k ; else k = Next[k] ; } } void KMP (){ int i = 0, j = 0 ; while (i < len2){ if (j == -1 || s1[j] == s2[i]){ i++ ; j++ ; } else j = Next[j] ; } if (j){ for (int k = 0; k < j; k++) cout << s1[k] ; cout << " " << j << endl ; } else cout << 0 << endl ; } int main (){ while (cin >> s1 >> s2 ){ len1 = s1.size() ; len2 = s2.size() ; getNext() ; KMP() ; } return 0 ; }
以上是关于kmp算法的主要内容,如果未能解决你的问题,请参考以下文章