模式匹配算法BF和KMP
来源:互联网 发布:八皇后问题 java递归 编辑:程序博客网 时间:2024/06/11 13:38
BF(Brute-Force)算法
步骤:
1:利用计数指针i和j指示主串S和模式T中当前正在比较的字符的位置,i的初始值pos可为任意小于主串S长度的值,j初值为1;
2:若两串均未比较到串尾
a:若S[i]=T[j],则i和j分别指示串中的下一个位置,继续比较后面的字符;
b:若S[i]不等于T[j],则指针后退重新比对,从主串的下一个字符(i=i-j+2)起重新开始和模式T的第一个字符比较
3:若j>T.length,说明匹配成功,返回和模式T中第一个匹配相等的字符在主串S中的序号(i-T.length);否则,返回0
注意:数组下标从1开始计数,所以i=i-j+2;
算法描述(c++):
int BF(string S,string T,int pos)
{
int i,j;
i=pos;j=1;
while(i<=S.length&&j<=T.length){
if(S[i]==T[j]){
i++;
j++;
}
else{
j=1;
i=i-j+2;
}
}
if(T.length<j)
return i-T.length;
return 0;
}
匹配过程:
S:aaaaaba
T:aab i=pos=1,j=1 i=2;j=1 i=3,j=1;
第一次匹配:a a a a a b a 第二次匹配:a a a a a b a 第三次匹配:a a a a a b a
a a b a a b a a b
i=3,j=3; i=4,j=3 i=5,j=3;
i=4,j=1
第四次匹配: a a a a a b a
a a b
i=7,j=4
返回i-T.length=7-3=4
KMP算法(改进的BF算法)
例1:
S:abcdefab
T:abcdex
第一次匹配:a b c d e f a b 第二次匹配:a b c d e f a b 第三次匹配:a b c d e f a b
a b c d e x a a
i=6,j=6i=2,j=1; i=3,j=1;
第四次匹配:a b c d e f a b 第五次匹配:a b c d e f a b 第六次匹配:a b c d e f a b
a a a
i=4,j=1 i=5,j=1; i=6,j=1
通过观察我们可以看出,对于匹配的子串T来说,“abcdex”首字母‘a’与后面的串“bcdex”中任意一个字符都不相等,对于第一步而言,前五位字符分别相等,这就意味着T的首字符不可能与S串中的第二位到第五位的字符相等,所以第二步到第五步都是多余的。
例2:
S:abcababca...
T:abcabx
第一次匹配:a b c a b a b c a... 第二次匹配:a b c a b a b c a... 第三次匹配:a b c a b a b c a...
a b c a b x a a
i=6,j=6 i=2,j=1 i=3,j=1
第四次匹配:a b c a b a b c a... 第五次匹配:a b c a b a b c a... 第六次匹配:a b c a b a b c a ...
a a b a b c
i=4,j=1 i=5,j=2 i=6,j=3
通过观察我们可以发现,第二步和第三步是多余的。
T的首位‘a’和T的第四位‘a’相等,第二位‘b’和第五位‘b’相等,而在第一步,第四位的‘a’和第五位的‘b’已和主串S中的相应位置比较过,是相等的,因此可以判断,T的第一位和第二位的字符与S的第四位和第五位也不用比较了,所以第四次和第五次也是多余的。
在BP算法中,主串的i值需要不断地回溯,而通过上面的例子可以看出i回溯可以不需要,KMP算法就是避免不必要的回溯发生。
既然i值不能回溯,那就考虑j值得变化,通过观察可以发现例1中T=“abcdex”,当中没有任何重复的字符,所以j由6变成1,而例2中T=“abcabx”,前缀的“ab”与最后“x”之前串的后缀“ab”相等,所以j由6变成3,因此我们可以得出规律,j值取决于当前字符之间的串的前后缀的相似度。
把T串中各个位置的j值得变化定义为一个数组next,next的长度就是T的长度,next[1]=0
next数组的推导
T="abcdex"
j:1 2 3 4 5 6
T: a b c d e x
next[j]: 0 1 1 1 1 1
1)当j=1时,next[1]=0;
2)当j=2时,j由1到j-1就只有字符‘a’,next[2]=1;
3)当j=3时,j由1到j-1的字符串“ab”,显然“a”不等于“b”,next[3]=1;
4)同理,所以T串的next[j为011111
T=“abcabx”
j:1 2 3 4 5 6
T:a b c d e x
next[j]: 0 1 1 1 2 3
1)当j=1时,next[1]=0;
2)当j=2时,j由1到j-1就只有字符‘a’,next[2]=1;
3)当j=3时,j由1到j-1的字符串“ab”,显然“a”不等于“b”,next[3]=1;
4)当j=4时,j由1到j-1的字符串“abc”,显然不相等,next[4]=1;
5)当j=5时,j由1到j-1的字符串“abca”,前缀字符a与后缀字符“a”相等,因此可推算出next[5]=2;
6)当j=6时,j由1到j-1的字符串“abcab”,前缀“ab”与后缀“ab”相等,next[6]=3;
算法实现
void get_next(string T,int *next)
{
int i,j;
i=0;
j=1;
next[1]=0;
while(j<T.length())
{
if(i==0||T[j]==T[i])
{
++i;
++j;
next[j]=i;
}
else
i=next[i];
}
}
{
int i,j;
i=0;
j=1;
next[1]=0;
while(j<T.length())
{
if(i==0||T[j]==T[i])
{
++i;
++j;
next[j]=i;
}
else
i=next[i];
}
}
int KMP(string S,string T,int pos)
{
int i=pos;
int j=1;
int next[255];
get_next(T,next);
while(i<=S.length()&&j<=T.length())
{
if(j==0||S[i]==T[i])
{
++i;
++j;
}
else
j=next[j];
}
if(j>T.length())
return i-T.length();
return 0;
}
{
int i=pos;
int j=1;
int next[255];
get_next(T,next);
while(i<=S.length()&&j<=T.length())
{
if(j==0||S[i]==T[i])
{
++i;
++j;
}
else
j=next[j];
}
if(j>T.length())
return i-T.length();
return 0;
}
KMP算法改进
例:
S=“aaaabcd”
T=“aaaaax”
1:a a a a b c d 2: a a a a b c d 3:a a a a b c d 4:a a a a b c d 5:a a a a b c d 6:a a a a b c d
| | | | | |
a a a a a x a a a a a x a a a a a x a a a a a x a a a a a x a
i=5,j=5 i=5,j=4 i=5,j=3 i=5,j=2 i=5,j=1 i=6,j=1
如上面的例子,next数组值是012345,通过观察发现,2345步骤是多余的,由于第二,三,四,五位置的字符斗鱼首位‘a相等,可以用首位的next【1】的值去取代后续的next【j】的值,因此增加一个取代的数组nextval
nextval数组推导
T=“ababaaaba”
j:1 2 3 4 5 6 7 8 9
T:a b a b a a a b a
next[j]:0 1 1 2 3 4 2 2 3
nextval[j]:0 1 0 1 0 4 2 1 0
1)当j=1时,nextval[1]=0;
2)当j=2时,第二个字符‘b’的next值是1,第一位是‘a’,不相等,所以nextval[2]=next[2]=1,维持原值
3)当j=3时,第三个字符‘a’的next值是1,第一位是‘a’,相等,所以nextval[3]=nextval[1]=0;
以此类推
算法实现
void get_nextval(string T,int *next)
{
int i,j;
i=0;
j=1;
nextval[1]=0;
while(j<T.length())
{
if(i==0||T[j]==T[i])
{
++i;
++j;
if(T[i]!=T[j])
nextval[j]=i;
else
nextval[j]=nextval[i];
}
else
i=nextval[i];
}
}
int i,j;
i=0;
j=1;
nextval[1]=0;
while(j<T.length())
{
if(i==0||T[j]==T[i])
{
++i;
++j;
if(T[i]!=T[j])
nextval[j]=i;
else
nextval[j]=nextval[i];
}
else
i=nextval[i];
}
}
0 0
- 模式匹配算法BF和KMP
- 数据结构- 串的模式匹配算法:BF和 KMP算法
- 串的模式匹配算法:BF和KMP算法
- 字符串模式匹配(BF算法和KMP算法)
- 串模式匹配之BF算法和KMP算法
- 数据结构- 串的模式匹配算法:BF和 KMP算法
- 串的模式匹配算法:BF和 KMP算法
- 串模式匹配之BF和KMP,Sunday算法
- 数据结构 模式匹配BF和KMP算法实现
- 字符串模式匹配算法--BF & KMP算法
- KMP与BF模式匹配算法
- 模式匹配之(BF KMP算法)
- 字符串匹配BF算法和KMP算法
- 字符串匹配算法(BF和KMP)
- 串的模式匹配算法(BF算法和KMP算法)
- 字符串模式匹配中BF算法和KMP算法的java实现
- (五)串的模式匹配——BF算法和KMP算法
- 字符串模式匹配的BF算法与KMP算法
- ThinkPad 关掉触摸板
- 个人记录-LeetCode 35. Search Insert Position
- 新闻发布项目——分页公共类(PageUitl )
- iOS开发之获取系统相册中的图片与视频(内带url转换)
- C++的数组遍历方法
- 模式匹配算法BF和KMP
- dbms_output 系统包
- oct、dec、hex、boolalpha的作用
- 运营进阶语言 — python
- Linux进程间通信
- 决策树的python实现
- 计数器
- Java和JavaScript中使用Json方法大全
- Struts2值栈详解