kmp算法例题

合集下载

串、KMP、矩阵_习题

串、KMP、矩阵_习题

1、一个n×n的对称矩阵,如果以相同的元素只存储一次的原则进行压缩存储,则其元素压缩后所需的存储容量为。

2、一个串的任意连续字符组成的子序列称为串的,该串称为。

3、串长度为0的串称为,只包含空格的串称为。

4、若两个串的长度相等且对应位置上的字符也相等,则称两个串。

5、寻找子串在主串中的位置,称为。

其中,子串又称为。

6、求出二维数组A[n,n]的两条对角线元素之和(程序题)。

基本知识字符串的操作C++中string类中相关操作的实现KMP矩阵压缩存储矩阵转置编程题1 、请编写一个函数,输入两个字符串,求他们的最长公共子序列。

例如:输入两个字符串ABCBDAB和BDCABA,字符序列BCBA和BDAB都是他们的最长公共子序列,则输出他们的长度4。

2 、给定一个源串和目标串,能够对串进行如下操作:(2012.Baidu、google)在给定位置上插入一个字符串。

替换任意字符删除任意字符使得源串等于目标串,源串和目标串的长度都小于2000。

求出相似度=(操作次数+1)/2。

注:距离=操作次数3、求数组的子数组之和的最大值。

4、递归(全排列)5、一个字符串中的任意一个子序列,若子序列中个字符值均相等,则称为字符平台。

写一算法,输入任意一字符串S,输出S中长度最大的所有字符平台的起始位置及所含字符。

注意:最大字符平台有可能不止一个。

例如:字符串“aabcbbbbdccccaaa”的最大字符平台是“bbbb”和“cccc”。

是第i行中值最小的元素,同时又是第j列中值最6、鞍点是指矩阵中的元素aij大的元素。

试设计一个算法求矩阵A的所有鞍点。

7、字符串反序。

实验04:串应用KMP算法PPT课件

实验04:串应用KMP算法PPT课件

在生物信息学中的应用
在生物信息学中,KMP算法被广泛应用于基因序列的比对和拼接,以及蛋白质序列 的匹配和比对。
通过构建基因序列或蛋白质序列的索引表,KMP算法可以在O(n+m)的时间复杂度 内完成序列的比对和拼接,提高了比对和拼接的准确性和效率。
KMP算法在生物信息学中的应用有助于深入了解基因和蛋白质的结构和功能,为生 物医学研究和疾病诊断提供了有力支持。
06 实验总结与展望
KMP算法的优缺点
优点
高效:KMP算法在匹配失败时能跳过 尽可能多的字符,减少比较次数,从
而提高匹配效率。
适用范围广:KMP算法适用于各种模 式串匹配问题,不受模式串长度的限 制。
缺点
计算量大:KMP算法需要计算和存储 部分匹配表,对于较长的模式串,计 算量较大。
不适合处理大量数据:KMP算法在处 理大量数据时可能会占用较多内存, 导致性能下降。
匹配失败的处理
当模式串中的某个字符与主串中的对应字符不匹配时,模式串向右 滑动,与主串的下一个字符重新对齐,继续比较
next[ j]表示当模式串中第j个字符与主 串中的对应字符不匹配时,模式串需 要向右滑动的位置。
next数组的构建
next数组的作用
在匹配过程中,通过next数组可以快 速确定模式串需要滑动到哪个位置, 从而提高了匹配效率。
通过已知的next值,递推计算出next 数组中其他位置的值。
KMP算法的时间复杂度
01
02
03
04
时间复杂度分析
KMP算法的时间复杂度取决 于模式串在主串中出现的次数 以及每次匹配所花费的时间。
最佳情况
当模式串在主串中连续出现时 ,KMP算法的时间复杂度为

c++实现KMP算法

c++实现KMP算法

c++实现KMP算法KMPKMP算法解决的问题字符串str1和str2,str1是否包含str2,如果包含返回str2在str1中开始的位置。

如何做到时间复杂度O(N)完成?思路:⾸先判断两个字符串是否为空串,并且str2的长度是否⼩于str1的长度,因为题⽬要求str1中包含str2。

以上都满⾜的情况下,⾸先定义两个变量分别为 x ,y 作为后续字符串中字符遍历的下标,然后再⽣成⼀个vector容器next,⽤来后续的匹配加速然后在str2中,做加速操作,也就是看当前 i - 1和之前的所有字符,有没有相同的,最⼤匹配长度。

从上图可以看到,下标0和1位置的值永远都是固定的-1和0,。

x 字符是 i 位置,x 前⾯的 c 是 i - 1 位置,也就是从下标0位置到5位置,找最⼤的匹配长度,然后填到 i 的next中。

这是循环中的case1如果当next中的值⼤于0的时候,从b开始,找到next中的2位置,然后跳转到当前位置的next中的坐标上,接着进⾏匹配。

最后如果到next为0或者-1的位置上,就标记当前位置为0,然后到下⼀个坐标继续判断。

当 i 遍历完str2后,循环结束,代表next中的值已经全部设置好了。

当str1 和 str2 没有循环遍历到尾部的时候,只要 str1 中 x 的位置等于 str2 中 y 的位置,x 和 y 就同时⾃增。

如果next中的值等于 -1 ,就说没有匹配成功,x 单独⾃增。

让str1往后挪⼀位如果str2中的没有匹配成功,就往前找next数组的值,只要不等于 -1 ,就⼀直执⾏这个往前移的过程。

最后看 y 是否已经到了str2的位置,如果到了就说明找到了,直接返回 x的位置减去 y的位置,就是匹配开始的位置,否则就是没有找到,直接返回 -1void getNextArray(string str, vector<int>& next){if (str.length() == 1){next.push_back(-1);}next.resize(str.length());next[0] = -1;next[1] = 0;int i = 2;int cn = 0;while (i < next.size()){if (str[i - 1] == str[cn]){next[i++] = ++cn;}else if (cn > 0){cn = next[cn];}else {next[i++] = 0;}}}int getIndexOf(string s, string m){if (s == "" || m == "" || s.length() < 1 || s.length() < m.length()){return -1;}int x = 0;int y = 0;vector<int> next;getNextArray(m,next);while (x < s.length() && y < m.length()){if (s[x] == m[y]){x++;y++;}else if (next[y] == -1){x++;}else {y = next[y];}}return y == m.length() ? x - y : -1;}以上就是c++ 实现KMP算法的详细内容,更多关于c++ KMP算法的资料请关注其它相关⽂章!。

kmp算法python代码

kmp算法python代码

kmp算法python代码摘要:1.KMP 算法简介2.KMP 算法的Python 实现3.KMP 算法的应用示例正文:1.KMP 算法简介KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用于在一个主字符串中查找一个子字符串出现的位置。

该算法的关键在于通过预处理子字符串,减少不必要的字符比较,从而提高匹配速度。

2.KMP 算法的Python 实现以下是KMP 算法的Python 实现:```pythondef compute_prefix_function(pattern):m = len(pattern)prefix_function = [0] * (m + 1)prefix_function[0] = 0i, j = 1, 0while i < m:if pattern[i] == pattern[j]:j += 1prefix_function[i] = ji += 1else:if j!= 0:j = prefix_function[j - 1]else:prefix_function[i] = 0i += 1return prefix_functiondef kmp_search(text, pattern):m, n = len(text), len(pattern)prefix_function = compute_prefix_function(pattern) i, j = 0, 0while i < m:if pattern[j] == text[i]:i += 1j += 1if j == n:return i - jelif i < m and pattern[j]!= text[i]:if j!= 0:j = prefix_function[j - 1]else:i += 1return -1if __name__ == "__main__":text = "我国是一个伟大的国家"pattern = "伟大的"result = kmp_search(text, pattern)if result!= -1:print("子字符串"{}" 在主字符串中第{} 位置出现。

KMP(模板)

KMP(模板)

KMP(模板)算法讲解:模板来源:⾸先:KMP的模板为:void get_next(char *a, int *nex) {nex[1] = 0;for (int i = 2, j = 0; i <= len; i++) {while (j > 0 && a[i] != a[j + 1])j = nex[j];if (a[i] == a[j + 1])j++;nex[i] = j;}return;}int KMP(char *a, char *b) {//b为母串for (int i = 1, j = 0; i <= strlen(b + 1); i++) {while (j > 0 && (j == strlen(a + 1) || b[i] != a[j + 1]))j = nex[j];if (b[i] == a[j + 1])j++;f[i] = j;//若a在b中出现,,返回出现的位置//if(f[i]==strlen(a+1)){return i-strlen(a);}}return1;}例题:题意:求字符串中的最短循环节,并输出该循环节KMP最⼩循环节、循环周期:定理:假设S的长度为len,则S存在最⼩循环节,循环节的长度L为len-next[len],⼦串为S[0…len-next[len]-1]。

(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。

(2)如果不能,说明还需要再添加⼏个字母才能补全。

需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。

注意这⾥的len是原字符串的len+1;1 #include<cstdio>2 #include<string.h>3 #include<algorithm>4using namespace std;5int T, len;6char s[100000 + 5];7int nex[100000 + 5];89void get_next(char* p, int next[]){10int pLen = strlen(p) + 1;//要求循环节长度时这⾥才+111 next[0] = -1;12int k = -1;13int j = 0;14while (j < pLen - 1){15if (k == -1 || p[j] == p[k]){16 ++j;++k;17if (p[j] != p[k])18 next[j] = k;19else20 next[j] = next[k];21 }22else{23 k = next[k];24 }25 }26}2728int kmp(char* s, char* p){29int i = 0;30int j = 0;33while (i < sLen && j < pLen){34//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++35if (j == -1 || s[i] == p[j]){36 i++;37 j++;38 }39else{40//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j] 41//next[j]即为j所对应的next值42 j = nex[j];43 }44 }45if (j == pLen)46return i - j;47else48return -1;49}5051int main() {52 scanf("%d", &T);53while (T--) {54 memset(nex, 0, sizeof(nex));55 scanf("%d", &len);56 scanf("%s", s);57 len = strlen(s);58 get_next(s, nex);59 printf("%d\n", len - nex[len]);60for (int i = 0; i < len - nex[len]; i++)61 printf("%c", s[i]);62 printf("\n");63 }64return0;65 }(数字KMP)1 #include<cstdio>2 #include<string.h>3 #include<algorithm>4using namespace std;5int T, len;6int len1, len2;7int s1[1000000 + 5];8int s2[1000000 + 5];9int nex[1000000 + 5];1011void get_next(int* p, int next[]) {12int pLen = len2;//要求循环节长度时这⾥才+113 next[0] = -1;14int k = -1;15int j = 0;16while (j < pLen - 1) {17if (k == -1 || p[j] == p[k]) {18 ++j; ++k;19if (p[j] != p[k])20 next[j] = k;21else22 next[j] = next[k];23 }24else {25 k = next[k];26 }27 }28}2930int kmp(int* s, int* p) {31int i = 0;32int j = 0;35 get_next(s2, nex);36while (i < sLen && j < pLen) {37//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++38if (j == -1 || s[i] == p[j]) {39 i++;40 j++;41 }42else {43//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j] 44//next[j]即为j所对应的next值45 j = nex[j];46 }47 }48if (j == pLen)49return i - j;50else51return -1;52}5354int main() {55 scanf("%d", &T);56while (T--) {57 scanf("%d %d", &len1, &len2);58for (int i = 0; i < len1; i++)59 scanf("%d", &s1[i]);60for (int i = 0; i < len2; i++)61 scanf("%d", &s2[i]);62if (kmp(s1,s2) == -1)63 printf("-1\n");64else65 printf("%d\n", kmp(s1,s2)+1);66 }67return0;68 }。

扩展KMP算法

扩展KMP算法

如何求解next[]数组 如何求解next[]数组 next[]
还剩下一个问题:next[]这个辅助数组怎 么计算?复杂度是多少? 我们发现计算next实际上以 为母串、T 实际上以T为母串 实际上以 为母串、 为子串的一个特殊“扩展的KMP”。用上 为子串的一个特殊“扩展的 ” 文介绍的完全相同的算法计算next即可。 (用next本身计算next,具体可以参考标准 KMP)此不赘述。
Thank you!
容易发现,如果有某个位置i满足 extend[i]=m,那么T就肯定在S中出现过, 并且进一步知道出现首位置是i——而这正 是经典的KMP问题。 因此可见“扩展的KMP问题”是对经典 KMP问题的一个扩充和加难。
例子 S=’aaaaaaaaaabaa a’, T=’aaaaaaaaaaa’。
比如ababab ,next[2] = 4, 2,3匹配0,1 ;然后4,5匹配2,3;相当 于还是匹配0,1 ;所以0,1被重复了3次, 所以只要是能匹配上的,就是在重复前i个 字符 ,能匹配多长,就是重复了多长,直 接用i+next[i]就是最长的长度 。
求解extend数组的模板
void GetExtand(const EleType str[], int strLen, int extand[], const EleType mode[], int modeLen, int next[]) { int i, a, p, j(-1); for (i = 0; i < strLen; ++i, --j) { if (j < 0 || i + next[i - a] >= p) { if (j < 0) j = 0, p = i; while (p < strLen && j < modeLen && str[p] == mode[j]) ++p, ++j; extand[i] = j, a = i; } else extand[i] = next[i - a]; } }

KMP算法

KMP算法
KMP算法
有动画,建议下载后观看
第1页,共25页。
有这样一个字符串:
BBC ABCDAB ABCDABCDABDE
我想知道,里面是否包含另一个字符串
ABCDABD
第2页,共25页。
首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第 一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。
第19页,共25页。
下面介绍《NEXT值表》是如何产生的。
第20页,共25页。
第一位的next值必定为-1; 计算第n个字符的NEXT值:
1.查看第n-1个字符对应NEXT值,设为a;
2.判断a是否为-1,若为-1,则第n个字符next值为0
3.若不为-1,将第n-1个字符与第a个字符比较 4.如果相同,第n个字符对应的NEXT值为a+1 5.如果不同,令a等于第a个字符的NEXT值,执行第第2步。
继续把它向后移,这样就提高了效率。
BBC ABCDAB ABCDABCDABDE
ABCDABD
第11页,共25页。
怎么利用这个已知信息呢?
第12页,共25页。
可以针对搜索词,算出一张《NEXT值表》,即失败指针。
这张表是如何产生的,等下再介绍,这里只要会用就可以了。
第13页,共25页。
已知空格与D不匹配时,前面六个字符"ABCDAB"是匹配的。查表可知,字符D 对应的“NEXT值"为2,因此按照下面的公式算出向后移动的位数:
BBC ABCDAB ABCDABCDABDE ABCDABD
第18页,共25页。
逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要

KMP几道入门题目

KMP几道入门题目

KMP⼏道⼊门题⽬HDU 1711 Number Sequence(模板题)#include<stdio.h>#include<string>const int maxn=1e6+10;const int maxm=1e4+10;int t,n,m,s[maxn],p[maxn];int next[maxm];void GetNext(){int plen=0;int slen=-1;next[0]=-1;while(plen<m){if(slen==-1||p[plen]==p[slen]){plen++;slen++;if(p[plen]!=p[slen])next[plen]=slen;else next[plen]=next[slen];}else slen=next[slen];}}int kmp(){int plen=0;int slen=0;while(plen<m&&slen<n){if(plen==-1||p[plen]==s[slen]){plen++;slen++;}else plen=next[plen];}if(plen==m)return slen-plen+1;else return -1;}int main(){scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=0;i<n;i++)scanf("%d",&s[i]);for(int i=0;i<m;i++)scanf("%d",&p[i]);GetNext();printf("%d\n",kmp());}return0;}View CodeHDU 2087 剪花布条求⼀个串在另⼀个串中的出现次数,KMP模板题#include<iostream>#include<string>using namespace std;string s,p;int plen,slen,Next[1010];void GetNext(){int j=0;int k=-1;Next[0]=-1;while(j<plen){if(k==-1||p[j]==p[k]){j++;k++;if(p[j]!=p[k])Next[j]=k;else Next[j]=Next[k];}else k=Next[k];}}int kmp(){int j=0;int i=0;int count=0;while(j<plen&&i<slen){if(j==-1||p[j]==s[i]){j++;i++;}else j=Next[j];if(j==plen){j=0;count++;}}return count;}int main(){while(cin>>s&&s[0]!='#'){cin>>p;plen=p.size();slen=s.size();GetNext();printf("%d\n",kmp());}return0;}View CodeHDU 2594 Simpsons’ Hidden Talents (next函数应⽤)#include<iostream>#include<string.h>using namespace std;const int maxn=5e5+10;char s1[maxn],s2[maxn];int Next[maxn],len1,len2,ans;void GetNext(){int k=-1;int j=0;Next[0]=-1;while(j<len1+len2){if(k==-1||s1[j]==s1[k]){j++;k++;Next[j]=k;}else k=Next[k];}}int main(){while(~scanf("%s%s",s1,s2)){len1=strlen(s1);len2=strlen(s2);strcat(s1,s2);GetNext();ans=Next[len1+len2];while(ans>len1||ans>len2)ans=Next[ans];if(ans){for(int i=0;i<ans;i++)printf("%c",s1[i]);printf(" %d",ans);printf("\n"); }else printf("%d\n",ans);}return0;}View Code。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

kmp算法例题
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。

举个例子,如果文本串S为'ABCABCABC',模式串P为'ABC',那么KMP算法会返回3个匹配位置,分别为0、3和6。

KMP算法的核心是利用模式串的信息来避免在文本串中不必要的比较。

具体来说,KMP算法维护一个next数组,用于记录模式串的前缀和后缀的最长公共长度。

在匹配过程中,如果一个字符与模式串不匹配,那么可以跳过一定长度的字符,直接比较后面的字符。

下面是一个KMP算法的示例代码:
```
vector<int> getNext(string p) {
int n = p.size();
vector<int> next(n, 0);
int j = 0;
for (int i = 1; i < n; i++) {
while (j > 0 && p[i] != p[j]) {
j = next[j - 1];
}
if (p[i] == p[j]) {
j++;
}
next[i] = j;
}
return next;
}
vector<int> kmp(string s, string p) { int n = s.size(), m = p.size();
vector<int> ans;
if (m == 0) {
return ans;
}
vector<int> next = getNext(p);
int j = 0;
for (int i = 0; i < n; i++) {
while (j > 0 && s[i] != p[j]) {
j = next[j - 1];
}
if (s[i] == p[j]) {
j++;
}
if (j == m) {
ans.push_back(i - m + 1);
j = next[j - 1];
}
}
return ans;
}
```
上面的代码中,getNext函数用于计算next数组,kmp函数用于查找模式串在文本串中的出现位置。

其中,i表示文本串的匹配位置,j表示模式串的匹配位置。

如果当前字符匹配成功(即S[i] == P[j]),则i和j都加1,继续匹配下一个字符;否则,i不变,j回溯到next[j-1]的位置,继续匹配下一个字符。

这里需要注意的是,getNext函数中j是指前缀的末尾位置,i 是指后缀的末尾位置。

在计算next数组时,如果当前字符不匹配,需要回溯到next[j-1]处重新匹配。

如果next[j-1]等于0,则说明不存在长度小于j且以P[j-1]为结尾的前缀,此时需要将next[i]
赋值为0。

相关文档
最新文档