首页 > 代码库 > 字符串模式匹配

字符串模式匹配

一、问题

  设有字符串s和pat,长度分别为LengthS和LengthP,在s中查找模式pat。

二、简单方法

  顺序考察s的第i(0<=i<=LengthS-LengthP)个位置,判断是否为一个匹配的起点,若成功,为S设置p指针,pat设置q指针,扫描判断是否匹配。

  时间复杂度O(LengthS*LengthP)。

三、KMP算法

  时间复杂度O(LengthP+LengthS)。

1、基本思想

  设s=s0,s1,...,s(m-1),pat=p0,p1,...p(n-1)

  当前比较si与pj:

  • 如果si==pj,则 i,j 各向前推进一步;
  • 如果si!=pj,        如果 j==0,则 i 向前推进一步,比较si+1与p0;
  •             如果 j>0,则设 y=p0,p1,...,p(j-1),x是y两头匹配的最大真子集,且 x=p0,p1,...,pk,则 p0,p1,..,pk==p(j-k-1),p(j-k-2),...,p(j-1)==s(i-k-1),s(i-k-2),...,s(i-1),可继续比较si与p(k+1)。

技术分享

2、失败函数

(1)定义

  模式p=p0,p1,...,p(n-1)的失败函数为

  f(j) = 最大的k<j,使得p0,...,pk==p(j-k),...,pj ,     如果这样的k>=0存在的话

                -1                                                           ,     否则

 

(2)实现

  已知f(0)=-1,假设已有 f(i-1),求 f(i)。

  如果 u=v,则 f(j)=f(j-1)+1,否则标记 f1(j)=f(j),fm(f)=f(fm-1(j))

  若 u=w则 f(j)=f2(j-1)+1,否则继续下去,直到找到某个m,使第 fm(j-1)+1个位置的字符与u相等,或者fm(j-1)=-1且第0个位置的字符仍然也不等于u。由此,失败函数的另一种定义形式:

  f(j) = -1          如果 j=0

     fm(j-1)+1      m是使得 p[fk(j-1)+1] = pj 的最小的k

     -1      如果上述k不存在

技术分享

3、代码

  两个字符串A,B,长度分别为lena和lenb,找到B在A中第一次出现的起始位置。若B未在A中出现,则返回-1。

int findAppearance(string A, int lena, string B, int lenb) {
        // write code here
        int f[10000];
        f[0]=-1;
        for (int j=1;j<lenb;j++){
            int fi=f[j-1];
            while ((B[j]!=B[fi+1]) && (fi>0))
                fi=f[fi];
            if (B[j]==B[fi+1])
                f[j]=fi+1;
            else
                f[j]=-1;
        }
        
        int i=0, j=0;
        while ((i<lena)&&(j<lenb)){
            if (A[i]==B[j]){
                i++;
                j++;
            }
            else if (j==0)
                i++;
            else
                j=f[j-1]+1;
        }
        if (j<lenb || lenb==0)
            return -1;
        else
            return (i-lenb);
    }

 

字符串模式匹配