计算过渡功能

时间:2012-05-04 07:31:04

标签: algorithm

如何使用π前缀函数为时间O(m |Σ|)计算字符串匹配自动机的转移函数δ的有效算法?

我想在有限自动机中计算过渡函数。正常转移函数具有O(m ^ 3 |Σ|)复杂度,其中m =模式P的长度,Σ是字母表。 COMPUTE_TRANSITION_FUNCTION(P,Σ)

m = length(P);
for  q = 0 through m  do
    for each character  x  in Σ
    k = min(m+1, q+2); // +1 for x, +2 for subsequent repeat loop to decrement
        repeat  k = k-1 // work backwards from q+1
        until  Pk 'is-suffix-of' Pqx;
        d(q, x) = k;    // assign transition table
end for; end for;

return  d;
End algorithm.

π是KMP算法中定义的前缀函数

2 个答案:

答案 0 :(得分:1)

存在O(m。|Σ|)算法,并且由于事务函数具有O(m。|Σ|)可能的输入,由于时间复杂性,没有更好的算法。

假设我们计算了π,我们想要计算d(q,x)。 d(q,x)表示我们应该进入哪个状态,如果我们当前处于状态q并且输入中的当前字符是x。如果当前字符是P [q],我们应该进入状态q + 1,因为q + 1字符匹配。所以d(q,p [i])= q + 1.否则我们必须进入数字较低的状态。 π[q]表示q之前的最后状态,P [0 ...π[q]]是P [0 ... q]的后缀。所以我们将状态π[q]的输出复制到状态q的输出,除了我们先前设置的字符p [i]。

我希望你理解它!

答案 1 :(得分:0)

我得到了一个需要O(m ^ 2 | E |)的答案。还有一个关于主题的问题32.4-8。

这是:

vector<vector<size_t>> Preprocess(const string &_pattern)
{
    vector<string> pattern_vec;
    for (size_t i = 0; i <= _pattern.size(); ++i)                                         // m
        pattern_vec.push_back(_pattern.substr(0, i));

    vector<vector<int>> is_match_matrix(1 + _pattern.size(), vector<int>(1 + _pattern.size(), -1));
    for (size_t i = 0; i < is_match_matrix.size(); ++i)                                            // m
    {
        for (size_t j = 0; j <= i; ++j)                                                      // m
        {
            if (pattern_vec[i - j] == _pattern.substr(j, i - j))
            {
                is_match_matrix[i][j] = i - j;
            }
        }
    }

    // note:
    is_match_matrix[_pattern.size()][0] = -1;

    vector<vector<size_t>> status_matrix(1 + _pattern.size(), vector<size_t>(26, 0));

    for (size_t i = 0; i < status_matrix.size(); ++i)                                            // m
    {
        char c = 'a';
        while (c <= 'z')                                                                         // E
        {
            for (size_t j = 0; j <= i; ++j)                                                      // m
            {
                if (-1 != is_match_matrix[i][j] && c == _pattern[is_match_matrix[i][j]])
                {
                    status_matrix[i][c - 'a'] = is_match_matrix[i][j] + 1;
                    break;
                }
            }

            c++;
        }
    }

    return status_matrix;
}