Algorithm_字节匹配_004_Boyer-Moore


    static INT MatchBytesBM(IN const UCHAR* pText, IN INT iTextBytes, IN const UCHAR* pPattern, IN INT iPatternBytes, IN BOOL bCheckParameter = TRUE); // 内存字节匹配;Boyer-Moore算法;

INT DiySystem::MatchBytesBM(IN const UCHAR* pText, IN INT iTextBytes, IN const UCHAR* pPattern, IN INT iPatternBytes, IN BOOL bCheckParameter /*= TRUE*/)
{
    //    Boyer-Moore
    //    BM算法是目前被认为最高效的字符串搜索算法,比KMP算法快3-5倍。
    //
    //    从右往左进行比较匹配。
    //    假设文本串pText长度N,模式串pPattern长度M
    //    好后缀规则和坏后缀规则:后移步长j += max(好后缀后移步长,坏后缀后移步长)
    //-->
    //HERE IS A SIMPLE EXAMPLE
    //EXAMPLE
    //坏后缀S(PText中),在文本串下标6,在模式串正本-1,坏后缀后移步长6-(-1)=7
    //无好后缀
    //-->
    //HERE IS A SIMPLE EXAMPLE
    //       EXAMPLE      
    //坏后缀P(PText中),在文本串下标6,在模式串正本4,坏后缀后移步长6-4=2
    //无好后缀
    //-->
    //HERE IS A SIMPLE EXAMPLE
    //         EXAMPLE
    //坏后缀I(PText中),在文本串下标2,在模式串正本-1,坏后缀后移步长2-(-1)=3    
    //好后缀MPLE(PText中),    
    //M在文本串下标6,在模式串正本0,后移步长6-0=6
    //P在文本串下标5,在模式串正本5,后移步长5-5=0
    //L在文本串下标4,在模式串正本4,后移步长4-4=0
    //E在文本串下标3,在模式串正本3,后移步长3-3=0
    //好后缀后移步长=max(6,0,0,0)
    //后移步长 = max(6,3)
    //-->
    //HERE IS A SIMPLE EXAMPLE
    //               EXAMPLE
    //坏后缀P(PText中),在文本串下标6,在模式串正本4,坏后缀后移步长6-4=2
    //无好后缀
    //-->
    //HERE IS A SIMPLE EXAMPLE
    //                 EXAMPLE    

    if (bCheckParameter)
    {
        if (!pText || iTextBytes <= 0 || !pPattern || iPatternBytes <= 0 || iPatternBytes > iTextBytes || IsBadReadPtr(pText, iTextBytes) || IsBadReadPtr(pPattern, iPatternBytes))
        {
            return -1;
        }
    }

    //模式串字节首次出现下标表,[字节值]=下标,-1未出现该字符
    vector<INT> vecPatternIndex(BYTE_MAX + 1, -1);
    for (INT i = 0; i < iPatternBytes; i++)
    {
        if (-1 == vecPatternIndex[pPattern[i]]) // 存储首次出现下标
        {
            vecPatternIndex[pPattern[i]] = i;
        }
    }

    for (INT i = 0, iBad = 0, iGood = 0, iSkip = 0; i <= iTextBytes - iPatternBytes;)
    {
        iBad = 0;
        iGood = 0;
        for (INT j = iPatternBytes - 1; j >= 0; j--)
        {
            if (pPattern[j] != pText[i + j])
            {
                break;
            }
            iGood++; // 好字符个数
        }
        if (iGood == iPatternBytes)
        {
            return i;
        }
        else
        {
            iBad = iPatternBytes - iGood - 1; // 坏字符在文本串下标
            if (iPatternBytes - 1 == iBad) //无好后缀
            {
                i += (iBad - vecPatternIndex[pText[i + iBad]]); // vecPatternIndex[pText[i + iBad]] 坏字符在模式串首出现下标
            }
            else
            {
                iSkip = 0;
                for (INT j = iPatternBytes - 1, k = 0; k < iGood; j--, k++)
                {
                    // 右向左遍历所有好字符,max(好字符在文本串下标-好字符在模式串首出现下标,...)
                    if (iSkip < j - vecPatternIndex[pText[i + j]]) // j 好字符在文本串下标
                    {
                        iSkip = j - vecPatternIndex[pText[i + j]]; // vecPatternIndex[pText[i + j]] 好字符在模式串首出现下标
                    }
                }
                if (iSkip < iBad - vecPatternIndex[pText[i + iBad]]) // max(好字符步长,坏字符步长 )
                {
                    iSkip = iBad - vecPatternIndex[pText[i + iBad]];
                }
                i += iSkip;
            }
        }
    }
    return -1;
}

猜你喜欢

转载自www.cnblogs.com/dailycode/p/9644405.html