模式匹配算法

转载至:http://www.cnblogs.com/mikelin/archive/2010/08/10/1796607.html

模式匹配

模式匹配的具体含义是在主串s中从start开始查找一个与模式串t相同的子串。如果找到则返回模式串t的第一个字符在主串中的下标;如果未找到则返回-1。

 

1.模式匹配的Brute-Force算法

Brute-Force算法实现模式匹配的思想是:从主串s=”s0s1…sn-1”的第一个字符开始和模式串t=”t0t1…tn-1”的第一个字符比较,若相等,则继续比较后续字符;否则从主串s的第二个字符开始重新与模式串t的第一个字符比较。如此不断继续,若存在模式串中的每个字符依次和主串中的一个连续字符序列相等,则匹配成功,返回模式串t的第一个字符在主串中的下标;否则匹配失败,返回-1。

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相同的子串
} // Index_BF

 

 

2.模式匹配的 KMP 算法

KMP 算法的思想是:设s为主串,t为模式串,设i为主串s当前比较字符的下标,j为模式串t当前比较字符的下标,另i和j的初值为0. 当si= tj时,i和j分别增1再继续比较;否则i不变,j改变为等于next[j],再继续比较。依次类推,直到下列两种情况之一:一种是j退回到某个j = next[j] 时有s= tj;则i和j分别增1再继续比较;另一种是j退回到j = -1,此时令主串和模式串的下标各增1(此时模式串下标便退回0:j = j + 1 = -1 + 1 = 0),再继续比较。

 

其中,我们把模式串中从第一个字符开始到任一个字符为止的模式串中的真子串定义为next[j]函数,则next[j]函数定义为:

①next[j]= max{ k | 0<k<j 且“t0t1…tk-1” = “tj-ktj-k+1…tj-1”}     当此集合非空时

②next[j]= 0                                         其他情况

③next[j]= -1                                        当 j = 0 时

若模式串t中存在真子串“t0t1…tk-1” = “tj-ktj-k+1…tj-1”,且满足0<k<j,则next[j]表示当模式串t中的tj与主串s的si比较不相等时,模式串t中需重新和主串s的si比较的字符下标为k,即下一次开始比较si和tk;若模式串t中不存在如上所说的真子串,有next[j] = 0,则下一次开始比较si和t0;当j = 0时,令next[j] = -1,此处-1为一标记,表示下一次开始比较si+1和t0.

 

简而言之,KMP算法对Brute-Force算法的改进就是利用已经得到的部分匹配结果将模式串t右滑一段距离再继续比较,从而无需回退主串s的下标值。

 

#include <iostream>
#include <string>
using  namespace  std;
 
void  get_nextval( const  char  *T, int  next[])
{
     // 求模式串T的next函数值并存入数组 next
     int  j = 0, k = -1;
     next[0] = -1;
     
     while  ( T[j] != '\0'  )
     {
         if  (k == -1 || T[j] == T[k])
         {
             ++j;
             ++k;
             next[j] = k;
         } // if
         else
             k = next[k];
     } // while
     
     这里是我加的显示部分
     // for(int  i=0;i<j;i++)
     //{
     //     cout<<next[i];
     //}
     //cout<<endl;
 
} // get_nextval 
 
int  KMP( const  char  *Text, const  char * Pattern)
{
     if ( !Text||!Pattern||  Pattern[0]== '\0'   ||  Text[0]== '\0'  )
         return  -1; //空指针或空串,返回-1
 
     int  len=0;
     const  char  * c=Pattern;
     
     while (*c++!= '\0' ) //计算模式串长度
     {
         ++len;
     }
     
     int  *next= new  int [len+1];
     get_nextval(Pattern,next); //求Pattern的next函数值
     
     int  index=0,i=0,j=0;
     while (Text[i]!= '\0'   && Pattern[j]!= '\0'  )
     {
         if (Text[i]== Pattern[j])
         {
             ++i; // 继续比较后继字符
             ++j;
         }
         else
         {
             index += j-next[j];
             if (next[j]!=-1)
                 j=next[j]; // 模式串向右移动
             else
             {
                 j=0;
                 ++i;
             }
         }
     } //while
     
     delete  []next;
     if (Pattern[j]== '\0' )
         return  index; // 匹配成功
     else
         return  -1;
}
 
int  main() //abCabCad
{
     char * text= "bababCabCadcaabcaababcbaaaabaaacababcaabc" ;
     char *pattern= "abCabCad" ;
     
     cout<<KMP(text,pattern)<<endl;
     return  0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值