shift-And Algorithm

  最近在研究一些字符串匹配算法,也是由于工作上的需要,强力推荐一本书《柔性字符串匹配》,一本很好的书。网上可以随时搜索到。还是说正题吧。

  Shift-And Algorithm 匹配源于KMP算法,但是比KMP算法简单的多。至于KMP如果不懂可以去参造数据结构这本书(严蔚敏版的)。为什么Shift-And Algorithm很简单呢?因为它用一个表,用位并行来模拟匹配。算法思想:

  设掩码D=dm....d1来表示集合。现在介绍它的功能:D的第j位置为1当且仅当p1...pj是t1...ti的后缀(如果dm是1的时候,表示匹配成功)。其匹配过程:

当读入ti+1时,需要计算新的掩码D(这个相当于D,见伪代码)。D的第j+1位是1的当且仅当D的第j位为1(p1...pj是t1...ti的后缀)并且ti+1与pj+1相等。利用位的并行可用公式得出:

  D=((D<<1)|0m-11)&B[ti+1](D的初始状态为0m)。

(D<<1)是将D置为D的第i位。(相当于将p串第j位移一位,和B[ti+1]匹配。这样会发现如果D中的第j位为1了,且B[ti+1]的第j+1位也为1(指的是t中的ti+1字符在模式串p中和pj+1相等),这就匹配成功。反之不成功)。因为字符串为空串也是文本的后缀,所以要与0m-11位或操作(这个我自己也不太懂为什么,希望大神指点一下)。

 举一个书上的例子模式串“announce”,构建B表。

  

a

00000001

c

01000000

e

10000000

n

00100110

o

00001000

u

00010000

*

00000000

  对于a在B表中,表项是表示它的位置,其他字符类似。

 

ecnuonna

00000001

 

伪代码:

    

根据伪代码写的C++代码如下:

    

 1 #include <iostream>
 2 #include <string>
 3 #include <cmath>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 void matchString(const string & vSrcStr, const string& vPatternStr, vector<int>& voMatchPosVec)
 9 {
10     //preprocessing
11     int SrcStrLen = vSrcStr.size();
12     int PatternStrLen = vPatternStr.size();
13     int B[256];
14     for (int i=0; i<PatternStrLen; i++)
15     {
16         B[vPatternStr[i]] |= 1<<(PatternStrLen-1-i);
17     }
18 
19     //searching
20 
21     int D = 0;
22 
23     for (int Pos=0; Pos<SrcStrLen; Pos++)
24     {
25         D = ((D<<1)|1)&B[vSrcStr[Pos]];
26 
27         if (D&(1<<(PatternStrLen-1)))
28         {
29             voMatchPosVec.push_back(Pos-PatternStrLen+1);
30         }
31     }
32 }
33 
34 int main(void)
35 {
36     string SrcStr = "aaaba";
37     string PatternStr = "aa";
38 
39     vector<int> MatchPosVec;
40 
41     matchString(SrcStr, PatternStr, MatchPosVec);
42 
43     for(vector<int>::iterator Ix=MatchPosVec.begin(); Ix!=MatchPosVec.end(); Ix++)
44     {
45         cout<<*Ix<<endl;
46     }
47 
48     system("pause");
49     return 0;
50 }
View Code

 

posted @ 2014-08-22 12:53  simple boy  阅读(463)  评论(0编辑  收藏  举报