模式串匹配问题

问题描述:

给出模式串P和文本串T

有以下问题:1、模式串是否出现在文本串。2、文本串中出现模式串的所有位置。3、模式串在文本串出现的次数。(暂时想不出那么多)


对于上述的每个问题都可以逐个字符比较来找出答案。代码如下

    for(int i=0;i
n=len(T),m=len(S)。

显然上述算法的时间复杂度是O(n*m)。

对于k个模式串问题时,时间复杂度就是O(n*m*k)。


对于一个模式串的匹配问题,可以使用KMP算法。

KMP算法的核心在于利用模式串的特点,匹配失效时不是把模式串简单地后移一位,而是根据已匹配的部分进行移位。

        T:ababacabacadagh        S:abacab

                                                            ababadabacadagh

                               abacab

朴素算法中模式串S失效后,模式串向后一位,如下图

                           ababadabacadagh
                                 abacab

而在KMP算法中,模式串如下移位

                          ababadabacadagh

                                   abacab

由上图可知,字符比较的位置不变,依然在T的第6个字符,模式串向后移动两个位置。时间复杂度可以达到O(n)

进行这样的移位,需要先构造模式串的失效指针fail。

构造失效指针代码如下:

    int i,j;
    fail[0]=-1;
    j=-1;i=0;
    while(i

失效指针的使用:

        i=0;j=-1;
        while(i

通过KMP算法,单模式串匹配的时间复杂度就降为O(n+m)。

而在k模式串的情况下,可以对每个模式串使用KMP算法来进行匹配,设l=|所有模式串的长度之和|,则时间复杂度为O(kn+l)。

在模式串较多的时候,该方法就不好用了。


AC自动机就可以解决多模式串匹配问题。

可以使用Trie树改造来实现AC自动机。

代码如下:

struct ACTree
{
    int ch[maxnode][maxc];//ch[i][j]为i结点指向字符j的边,如果不存在则设为非法值
    int cot;//记录结点数量
    int fail[maxnode];//失效指针
    int val[maxnode];//结点储存的信息
    int newnode()
    {
        for(int i=0;iq;
        fail[0]=0;//根结点的失效指针指向根结点
        for(int i=0;i0)
                {
                    //对应操作
                }
                temp=fail[temp];
            }
        }
    }
};

AC自动机构造时,把结点不存在的边指向。在匹配时就不需要判断。即ch[u][i]=ch[fail[u]][i],不存在的边指向失效指针的对应字符结点。

这样匹配的时间复杂度为O(n),构造AC自动机的时间复杂度为O(l)。

总时间复杂度是O(l+n)。





你可能感兴趣的:(ACM学习)