匹配算法(网络摘抄)-KMP
来源:互联网 发布:mac word 繁简转换 编辑:程序博客网 时间:2024/06/18 16:05
所谓匹配就是在字符串里找另一个字串。简单匹配算法的时间复杂度为O(m*n),而KMP匹配算法可以证明它的时间复杂度为O(m+n)。
一、简单匹配算法
int Index_BF ( char S [ ], char T [ ], int pos ) { /* 若串 S 中从第pos(S 的下标0≤pos<StrLength(S))个字符起存在和串 T 相同的子串,则称匹配成功,返回第一个这样的子串在串 S 中的下标,否则返回 -1 */int i = pos, j = 0; while ( S[i+j] != '\0'&& T[j] != '\0') {if ( S[i+j] == T[j] ) j ++; // 继续比较后一字符else { i ++; j = 0; // 重新开始新的一轮匹配}}if ( T[j] == '\0') return i; // 匹配成功 返回下标else return -1; // 串S中(第pos个字符起)不存在和串T相同的子串}
此算法的思想是直截了当的:将主串S中某个位置i起始的子串和模式串T相比较。即从 j=0 起比较 S[i+j] 与 T[j],若相等,则在主串 S 中存在以 i 为起始位置匹配成功的可能性,继续往后比较( j逐步增1 ),直至与T串中最后一个字符相等为止,否则改从S串的下一个字符起重新开始进行下一轮的"匹配",即将串T向后滑动一位,即 i 增1,而 j 退回至0,重新开始新一轮的匹配。
例如:在串S=”abcabcabdabba”中查找T=” abcabd”(我们可以假设从下标0开始):先是比较S[0]和T[0]是否相等,然后比较S[1] 和T[1]是否相等…我们发现一直比较到S[5] 和T[5] 才不等。如图:
当这样一个失配发生时,T下标必须回溯到开始,S下标回溯的长度与T相同,然后S下标增1,然后再次比较。如图:
这次立刻发生了失配,T下标又回溯到开始,S下标增1,然后再次比较。如图:
又一次发生了失配,所以T下标又回溯到开始,S下标增1,然后再次比较。这次T中的所有字符都和S中相应的字符匹配了。函数返回T在S中的起始下标3。如图:
二、KMP匹配算法
还是相同的例子,在S=”abcabcabdabba”中查找T=”abcabd”,如果使用KMP匹配算法,当第一次搜索到S[5]和T[5]不等后,S下标不是回溯到1,T下标也不是回溯到开始,而是根据T中T[5]==’d’的模式函数值(next[5]=2,为什么?后面讲),直接比较S[5]和T[2]是否相等,因为相等,S和T的下标同时增加;因为又相等,S和T的下标又同时增加。。。最终在S中找到了T。如图:
三、怎么求串的模式值next[n]
定义:
(1)next[0]= -1 意义:任何串的第一个字符的模式值规定为-1。
(2)next[j]= -1 意义:模式串T中下标为j的字符,如果与首字符相同,且j的前面的1~k个字符与开头的1~k个字符不等(或者相等但T[k]==T[j])(1≤k<j)。如:T=”abCabCad”则 next[6]=-1,因T[3]=T[6]
(3)next[j]=k 意义:模式串T中下标为j的字符,如果j的前面k个字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)。即T[0]T[1]T[2]...T[k-1]==T[j-k]T[j-k+1]T[j-k+2]…T[j-1]
且T[j] != T[k].(1≤k<j);
(4) next[j]=0 意义:除(1)(2)(3)的其他情况。
例:求T=”ababcaabc”的模式函数的值。
next[0]= -1 根据(1)
next[1]=0 根据(4)
next[2]=-1 根据 (2)
next[3]=0 根据 (3) 虽T[0]=T[2]但T[1]=T[3] 被划入(4)
next[4]=2 根据 (3) T[0]T[1]=T[2]T[3] 且T[2] !=T[4]
next[5]=-1 根据 (2)
next[6]=1 根据 (3) T[0]=T[5] 且T[1]!=T[6]
next[7]=0 根据 (3) 虽T[0]=T[6]但T[1]=T[7] 被划入(4)
next[8]=2 根据 (3) T[0]T[1]=T[6]T[7] 且T[2] !=T[8]
即
下标
0
1
2
3
4
5
6
7
8
T
a
b
a
b
c
a
a
b
c
next
-1
0
-1
0
2
-1
1
0
2
只要理解了next[3]=0,而不是=1,next[6]=1,而不是= -1,next[8]=2,而不是= 0,其他的都容易理解。
next[n]意义:
next函数值究竟是什么含义,前面说过一些,这里总结。
设在字符串S中查找模式串T,若S[m]!=T[n],那么,取T[n]的模式函数值next[n],
1. next[n]= -1表示S[m]和T[0]间接比较过了,不相等,下一次比较 S[m+1]和T[0]
2. next[n]=0表示比较过程中产生了不相等,下一次比较 S[m] 和T[0]。
3. next[n]= k >0但k<n, 表示,S[m]的前k个字符与T中的开始k个字符已经间接比较相等了,下一次比较S[m]和T[k]相等吗?
4. 其他值,不可能。
代码段:
void getNext(const char* pattern,int next[]) { next[0]= -1; int k=-1,j=0; while(pattern[j] != '\0') { if(k!= -1 && pattern[k]!= pattern[j] ) k=next[k]; ++j;++k; if(pattern[k]== pattern[j]) next[j]=next[k]; else next[j]=k; } }
- 匹配算法(网络摘抄)-KMP
- KMP算法的摘抄
- 字符串匹配(KMP算法)
- 字符串匹配算法(KMP)
- kmp算法(字符串匹配)
- 字符串匹配(KMP算法)
- KMP算法(字符串匹配)
- 字符串匹配(KMP算法)
- 算法导论(九)kmp匹配算法
- 字符串匹配算法(二)-KMP算法
- 最长字符串匹配算法(KMP算法)
- 暴力匹配算法与KMP算法(串的匹配)
- kmp算法(用来处理字符串匹配)
- 快速模式匹配算法(KMP)
- 快速模式匹配算法(KMP)
- 字符串匹配的KMP算法(二)
- KMP模式匹配算法(1)
- KMP模式匹配算法(2)
- 使用Swing实现窗体震动效果(运用了Timer类)
- CCNotificationCenter处理消息事件
- Ununtu下载Android源代码
- 插入排序
- UVa 11317 GCD+LCM 欧拉函数log求位数
- 匹配算法(网络摘抄)-KMP
- Simpsons’ Hidden Talents (KMP)
- ASP.NET中Cookie的用法
- struts工作流程及各种文件详解
- oracle DBMS_SYSTEM
- VC2008下使用OpenSSL 1.0.0g(免编译)
- POJ 2528 离散化+线段树染色
- SQL Server性能调优:资源管理之内存管理篇(上)
- java中的ArithmeticException