zoukankan      html  css  js  c++  java
  • Shift And/Or字符串匹配算法

      Shift-And算法是一种基于前缀的单字符串匹配算法,采用位运算。其算法思想比KMP简单得多。

    在最简单的brute force算法中,在文本串的每个位置都要进行m(模式串长度)次比较,而SHIFT AND算法则是利用位运算提高这个过程。现在计算机的字长一般为3264位也开始流行了。一次比较的值为true or false,只需要一位即可存储,所以计算机可以在一次运算里完成位长次的比较。通过此思路可以把brute force的速度提高位长倍。

    Shift-And算法思想:设模式字符串为P,文本为text。它主要通过维护一个字符串集合DD中记录了P中所有与当前已读text的某个后缀相匹配的前缀),集合D中的每个字符串既是模式串p的前缀,同时也是已读入文本的后缀,每当从text中读入一个新的字符,算法立即利用位并行机制来更新集合D

     我们可以这么具体理解:

    •  P长度为m,则集合D可表示为D = dmd1 而用D[j]代表dj
    • D[j]=1,当且仅当p1pj t1ti 的某个后缀;
    • D[m]=1时,就认为P已经于text匹配;
    • 当读入下一个字符 ti+1, 需要计算新的集合 D′;
    • 当且仅当D[j]=1并且  ti+1等于pj+1D'[j+1]=1。这是因为D[j]=1时有 p1pj t1ti 的一个后缀,而当ti+1 等于 pj+1可推出p1pj +1 t1ti+1 的一个后缀。这个集合可通过位运算来更新。

    Shift-and算法首先建立一个数组B, 数组长度为字符集长度,B的第j位为1,表示则表示源串的i+1位与模式串的j位相同。设集合为D,则作位运算,((D<<1) + 1) & B即可得到新的D。

     1 int ShiftAndMatch(byte* pSrc, int nSrcSize, byte* pSubSrc, int nSubSrcSize)
     2 {
     3     long skip[256];
     4     memset(skip, 0, sizeof(skip));
     5     for (int i = 0; i < nSubSrcSize; i++)
     6     {
     7         skip[ pSubSrc[i] ] |= (0x01 << i);
     8     }
     9 
    10     long mask = 0x01<<(nSubSrcSize-1);
    11     long d = 0;
    12     int nPos = 0;
    13     while(nPos <= nSrcSize - nSubSrcSize)
    14     {
    15         d = ((d<<1)|0x01) & skip[pSrc[nPos]];
    16         if (d & mask)
    17         {
    18             break;
    19         }
    20         nPos++;
    21     }
    22     return nPos - (nSubSrcSize - 1); 
    23 }
    

       Shift-Or算法是Shift-And的一种技巧性的改进实现,其算法思想跟Shift-And类似,只是在通过对位取反以去掉公式中的掩码0m-11,这样减少了位运算的次数,从而实现加速。Shift-Or作的修改是,使用反码表示B中的位掩码和位向量,即用0表示一个数在集合里,1表示不在,所以将

    D = ((D<<1) | 1) & B[s[i]];

    修改为

    D=D<<1 | B[s[i]];

    这样就省了一次位运算,当然BD的初始化的时候,也要作相应的修改

     1 int ShiftOrMatch(byte* pSrc, int nSrcSize, byte* pSubSrc, int nSubSrcSize)
     2 {
     3     long skip[256];
     4     memset(skip, -1, sizeof(skip));
     5     for (int i = 0; i < nSubSrcSize; i++)
     6     {
     7         skip[pSubSrc[i]] ^= (0x01 << i);
     8     }
     9 
    10     long mask = ~(0x01 << (nSubSrcSize - 1 ));
    11     long d = -1;
    12     int nPos = 0;
    13     while(nPos <= nSrcSize - nSubSrcSize)
    14     {
    15         d = (d<<0x01) | skip[pSrc[nPos]];
    16         if (~(d|mask))
    17         {
    18             break;
    19         }
    20         nPos++;
    21     }
    22     return nPos - (nSubSrcSize - 1);
    23 
    24 }
  • 相关阅读:
    September 29th 2017 Week 39th Friday
    September 28th 2017 Week 39th Thursday
    September 27th 2017 Week 39th Wednesday
    September 26th 2017 Week 39th Tuesday
    September 25th 2017 Week 39th Monday
    September 24th 2017 Week 39th Sunday
    angular2 学习笔记 ( Form 表单 )
    angular2 学习笔记 ( Component 组件)
    angular2 学习笔记 ( Http 请求)
    angular2 学习笔记 ( Router 路由 )
  • 原文地址:https://www.cnblogs.com/dsky/p/2470882.html
Copyright © 2011-2022 走看看