我试图将C ++ Z-Algorithm实现改编成C#,我得出以下结论:
public static bool zAlgorithm(string pattern, string target)
{
string s = pattern + '$' + target;
int n = s.Length;
var z = new List<int>(new int[n]);
int goal = pattern.Length;
int r = 0, l = 0, i;
for (int k = 1; k < n; k++)
{
if (k > r)
{
for (i = k; i < n && s[i] == s[i - k]; i++) ;
if (i > k)
{
z[k] = i - k;
l = k;
r = i - 1;
}
}
else
{
int kt = k - l, b = r - k + 1;
if (z[kt] > b)
{
for (i = r + 1; i < n && s[i] == s[i - k]; i++) ;
z[k] = i - k;
l = k;
r = i - 1;
}
}
if ((z[k] == goal))
return true;
}
return false;
}
FWIW它有效,但我觉得它可能会更快。一个值得注意的区别是我使用列表而不是向量。尽管我的研究表明这是正确的数据结构,但我无能为力,但这个列表会有更大的开销。也许我错了,但我仍然主要想知道我能实现的最重要(如果有的话)优化是什么(以及其他任何人都愿意添加的)。感谢
答案 0 :(得分:0)
我最初重写了一些我在这篇文章中找到的C#代码:
https://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/
我在这里发布了它作为我的初步答案。
我结束了重写一些非常简洁的C代码:
上面的页面似乎是翻译:
http://codeforces.com/blog/entry/3107
我认为这段代码是最优的,但我仍然在努力弄清楚它是如何工作的。我可能会发布一些更新,因为我试图了解Z算法。
public static int Search(string text, string pattern, bool once = false)
{
var result = 0;
var concat = pattern + "$" + text;
var l = concat.Length;
var n = pattern.Length;
var za = new int[l];
GetZarray(concat, za);
for (var i = 0; i < l; ++i)
{
if (za[i] == n)
{
Console.WriteLine("Pattern found at index: {0}", i - n - 1);
result ++;
if (once) break;
}
}
return result;
}
private static void GetZarray(string str, int[] za)
{
var n = s.Length;
var l = 0;
var r = 0;
for (var i = 1; i < n; ++i)
{
if (i <= r) z[i] = Math.Min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
if (i + z[i] - 1 <= r) continue;
l = i;
r = i + z[i] - 1;
}
}
我将继续努力提供有关此代码如何工作的解释,并在将来将它们添加到此答案中。