16 - 12 - 20 KMP算法 模式匹配 终极奥义!
来源:互联网 发布:3dmax有没有mac版 编辑:程序博客网 时间:2024/05/17 23:00
尊重产权,转载请注明出处。
ex:找一个单词在一篇文章中的定位 问题 :这种子串的定位操作
通常叫做 串的模式匹配。
ex 我们要从 goodgoogle 中 找 google 这个单词。
朴素的方法是:
1、取子串的第一个字符叫做子首,主串 向后查找,
直到找到第一个与子首相等的字符叫做主首;
2、子首后移一位,主首后移一位,再次比较(重复此过程)
要是直到查找了n次(n = 子串长度),仍然是次次对应相等,
说明子串就是主串真正的子串。
3、比如:
主串:goodgoogle;
子串:google;主串一开始与子串比较,子串比较到 g-d 发现不相等了,指向主串的指针退回到第二个字符o再重复2过程,
ex-2 : (设 n 为主串长度,m 为子串长度):
主串:00000000000000000000000000000000000000000001 n=44
子串:0000000000000000001 m= 19;
需要比较的次数约为:(n-m)*m (比较简单)
其实这是完全没有必要的,因为 当比较到 g-d 时候,
我们就能知道前面的六个字符肯定都不符合,
根本不需要退回到主串的第二个字符重新搜索
那,有人会问,干嘛非要讨论这种极端情况呢?
不,其实真的很有必要!
因为当m 越小,出现这种低效匹配的概率越高,
而若当m 越大,所导致的后果也就越严重。
不过,蛮力算法也并不是一无是处,比如在实际情况如搜索引擎里,
n是对应着需要搜索的库,m是用户输入的关键字,
n相对m来说是远远大于m的,所以O(n-m+1)*m 也等于 O(n),
极端情况的概率也就变得很小了。
*************************KMP讲解:****************************
比如:比较 abcdefgab 和 abcdex
仔细观察发现:子串的首字符a 与其后的bcdex 都不相等,
那么对于主串abcdefgab 的 与子串对应相等的前五位而言已经失去了比较的意义。主串只需要直接跳转到f 开始比较就行。
那么主、子串要是这样:
S = abcabcabx
T = abcabx 观察到子串中T1 = T4, 这种情况怎么办呢?
可以确定S2 S3肯定是不用再次比较了,所以T只需要与S4 S5 对齐即可。
子串如何滑动与主串是没有关系的,因为出现失配的前面 肯定都是匹配的,
所以指向主串的计数变量 i 不动,指向模式串(子串)的计数变量 j 会根据next 来确定滑动距离。
下面我们就以失配前匹配的那一段前缀来构建next[ ]数组以期确定下一次子串滑动的方向
那么next 数组究竟启什么作用?
返回失配位之前的最长公共前后缀!
具体来讲,KMP算法想要解决的主要矛盾是子串的自匹配所造成的重复冗余。
↑ 其中一律取 0 :就是从模式串的第一个字符开始 重新比较呗,
模式串中 没有重复的部分,那我们的KMP 也就无用武之地了。
说了这么多,那如何构建一个next[]数组呢? ↓
<<<<<<<<<<代码君>>>>>>>>>>>
int main() { int next[10]; int pos = 0; char T[MAXSIZE],S[MAXSIZE]; printf("Please input the main string and the model string \n"); while(scanf("%s%s",S,T)) { Getnext(T,next); int result = KMP(S,T,pos,next); if(result) printf("We found it :%d \n\n",result); else printf("NO FOUND!v\n\n"); } system("pause") ; return 0;}
/* 在主串 S 的第 pos 个位置开始查找子串 T,返回模式串在主串中的位置*/
int Getnext(char *T,int next[]) { int j = 0 , k = -1;int tlen = strlen(T); next[0] = -1; while( j < tlen) { if(k == -1 || T[j] == T[k] ) { j++; k++; next[j] = k; } else k = next[k]; }}int KMP(char *S,char *T,int pos,int next[]) { int i = pos - 1; int j = 0; int slen = strlen(S); int tlen = strlen(T); while(i < slen && j < tlen) { if(j == -1 || S[i] == T[j]) { i++ ; j++ ; } else j = next[j]; } if(j >= tlen) return i - tlen + 1; else return -1;}
- 16 - 12 - 20 KMP算法 模式匹配 终极奥义!
- 模式匹配---KMP算法
- 模式匹配 KMP算法
- 模式匹配-KMP算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- 模式匹配kmp算法
- 模式匹配算法kmp
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP算法模式匹配
- 数据流图
- idea 创建maven web 项目时报错
- 移动应用实战(移动OA)之六_生成Android手机APP之一
- Memcached存Session数据、访问安全性、使用场景总结
- ubuntu14.04 lts rabbitVcs安装记录
- 16 - 12 - 20 KMP算法 模式匹配 终极奥义!
- 为什么volatile不能保证原子性而Atomic可以?
- 海龟绘图-python turtle学习笔记1
- RecyclerView 点击事件
- 分治 麦森数
- 1217File类简单的一些知识的理解
- Mac安装MySQL初始密码设置
- 单例模式和Rxjava遇到的问题
- 经受时间沉淀的15 个 Android 通用流行框架大全