如何使用π前缀函数为时间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算法中定义的前缀函数
答案 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;
}