horspool算法从右往左匹配,它跳转的时候只利用了一个字符的信息,这样使得跳转会比较短,速度比较慢。
BNDM算法是一种跳转时考虑子串的算法。具体实现的时候,为了提高速度,用了跟SHIFT AND一样的技巧。对于字符集里的每个字符,计算它在模式串的哪些位置出现,然后用一个整数表示这个集合。用一个整数D表示当前活跃的状态,第i位为1,表示在模式串i的位置有一个子串匹配到了,子串的具体长度取决于源串匹配的情况。如果D里第m位为1,这时候表示找到了模式串的一个前缀,如果这时候源串也匹配了m个字符,则表示找到了模式串,否则,只是一个子串,这时候要调整一个跳转的长度。跳转的长度为m-这个前缀的长度。每找到一个前缀都要更新一个跳转的距离,所以跳转的距离是越来越短。
1 int BNDMMatch(byte* pSrc, int nSrcSize, byte* pSubSrc, int nSubSrcSize) 2 { 3 unsigned int skip[256] = {0}; 4 for(int i = 0; i < nSubSrcSize; i++) 5 { 6 skip[ pSubSrc[i] ] |= 1 << (nSubSrcSize - 1 - i); 7 } 8 9 int nPos = 0; 10 while(nPos <= nSrcSize - nSubSrcSize) 11 { 12 int j = nSubSrcSize -1; 13 int last = nSubSrcSize; 14 unsigned int D = -1; 15 while(D) 16 { 17 D &= skip[pSrc[nPos + j]]; 18 if (D & (1<<(nSubSrcSize-1))) 19 { 20 if (j > 0) 21 { 22 last = j; 23 } 24 else 25 { 26 return nPos; 27 } 28 } 29 j--; 30 D <<= 1; 31 } 32 nPos += last; 33 } 34 return -1; 35 }