用于在boyer-moore字符串匹配算法中构造后缀表的O(n)算法

时间:2013-10-05 06:37:15

标签: string algorithm boyer-moore

我想实现boyer-moore算法但我仍然坚持构造一个好的后缀表,我认为它应该具有O(n)复杂度,我只找到了O(n ^ 2)算法。 那么你们有什么线索给我?

请不要给我代码片段,如果我愿意,我可以谷歌它,但我更喜欢以我的方式解决它,我只需要一个线索。

1 个答案:

答案 0 :(得分:0)

有一种使用前缀功能的快速算法。 字符串s的前缀函数是数组p,其中p [i]是子字符串s [0..i](0索引)及其后缀的前缀的最长长度。 可以使用使用2个事实的KMP以O(n)复杂度计算:

  1. P [I + 1] = P [I] 1
  2. 对于每个i,如果s [p [i]] == s [i + 1],则p [i + 1] = p [i] + 1.否则,我们应该尝试另一个字符串,其中s [0 ... J-1] == S [I-J + 1 ... i]中。显然,(我们选择最长的字符串)我们应该跳到i = p [i-1]的位置。
  3. 算法(c ++):

    vector<int> prefix (string s) 
    {
        int n=s.length();
        vector<int> pi(n);
        pi[0]=0;
        for (int i=1; i<n; ++i) 
        {
            int j = pi[i-1];
            while (j>0 && s[i]!=s[j])
                j=pi[j-1];
            if (s[i]==s[j])  ++j;
            pi[i]=j;
        }
        return pi;
    }
    

    现在我们可以构造后缀表:

    m = text.length();
    vector<int> suffshift(m);
    vector<int> pi = prefix(pattern);
    vector<int> pi1 = prefix(inverse(pattern));
    for (int j=0; j<m; ++j)
    {
        suffshift[j] = m - pi[m];
    }
    for (int i=1; i<m; ++i)
    {
         j = m - pi1[i];
         suffshift[j]=min(suffshift[j], i-pi1[i]);
    }
    

    Suffshift [m]代表整个文本的空后缀,即suppshift [0]。复杂性是O(n)。