KMP--找子串
来源:互联网 发布:勒夏特列原理 知乎 编辑:程序博客网 时间:2024/06/08 04:20
问题概述:输入两个数n和m,再依次输入n个数作为串a,再输入m个数作为串b,请判断b串是否为a的子串,若是则输出b串在a串的起始点
输入样例: 对应输出:
2 6
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
KMP算法(专用于求解字符串匹配问题)步骤:
①定义一个数组next[m]用于对应子串(b[m]),next[i]=j表示b[1~j]和b[i-j+1, i]完全相等且b[i]!=b[j]
②初始化i=j=1(串中第一个)
③i++, j++,如果a[i]==b[i]执行步骤5,否则执行步骤4
④b串向后挪,由b[j]对应a[i]变为b[next[j]]对应a[i](j=next[j]),如果next[j]==-1则表示a[i]完全不能对应字串b中的任何一个元素,i++, j=0
⑤判定是否已经匹配完毕,如果没有继续执行步骤3
(在最后3个步骤中,如果i超过a的范围,表示匹配失败,结束)
原理:http://www.matrix67.com/blog/archives/115
复杂度:O(n+m)
#include<stdio.h>#include<string.h>int n, m;int a[1000005], b[10005], next[10005];void getnext();int kmp();int main(void){int T, i;scanf("%d", &T);while(T--){scanf("%d%d",&n,&m);for(i=0;i<=n-1;i++)scanf("%d", &a[i]);for(i=0;i<=m-1;i++)scanf("%d", &b[i]);if(n<m){printf("-1\n");continue;}getnext();printf("%d\n", kmp());}return 0;}void getnext(){int i, j;i = 0, j = -1;next[0] = -1;while(i<m){if(j==-1 || b[i]==b[j]){i++, j++;if(b[i]==b[j])/*虽然到这里可以满足b[1~j]和b[i-j+1,i]完全相等,但是因为b[i]=b[j],如果b[i]无法匹配,那么b[j]一定无法匹配*/next[i] = next[j];elsenext[i] = j;}else /*如果b[i]和b[j]不相等,则说明后面不可能存在在i-j=k(k为定值)的情况下b[1~j]和b[i-j+1,i]完全相等,拉开i与j的距离*/j = next[j];}}int kmp(){int i, j;i = j = 0;while(i<n){if(a[i]==b[j])/*匹配成功,i++,j++,继续匹配*/{if(j==m-1)return i-j+1;i++, j++;}else{j = next[j];/*匹配不成功,b串向后挪,由b[j]对应a[i]变为b[next[j]]对应a[i],即j=next[j]*/if(j==-1)/*如果next[j]==-1表示a[i]完全不能对应字串b中的任何一个元素,i++,j=0*/i++, j = 0;}}return -1;}
阅读全文
1 0
- KMP--找子串
- KMP
- KMP
- KMP
- KMP
- KMP
- KMP
- kmp
- kmp
- KMP
- kmp
- KMP
- KMP
- KMP
- kmp
- KMP
- KMP
- kmp
- 方向梯度直方图(HOG)
- Linux
- 病毒、木马、蠕虫与恶意代码关键点
- TCP定时器讲解与TCP三次握手四次挥手
- 《java并发编程实战》笔记(第10章)
- KMP--找子串
- EffectiveC++学习笔记-条款32|33
- 结构算法 002 单链表的头插法和尾插法
- webView之post请求携带请求头及打印日志等剖析
- 前端经典面试题1
- python 字典
- 我的C程序设计语言学习日记#03
- 一维数组、二维数组、字符串总结
- JTable使用实例