优化Z算法的C#实现

时间:2016-07-15 15:58:28

标签: c# algorithm search time-complexity

我试图将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它有效,但我觉得它可能会更快。一个值得注意的区别是我使用列表而不是向量。尽管我的研究表明这是正确的数据结构,但我无能为力,但这个列表会有更大的开销。也许我错了,但我仍然主要想知道我能实现的最重要(如果有的话)优化是什么(以及其他任何人都愿意添加的)。感谢

1 个答案:

答案 0 :(得分:0)

我最初重写了一些我在这篇文章中找到的C#代码:

https://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/

我在这里发布了它作为我的初步答案。

我结束了重写一些非常简洁的C代码:

http://e-maxx.ru/algo/z_function&xid=17259,15700023,15700124,15700149,15700168,15700173,15700186,15700189,15700190,15700195,15700201,15700205&usg=ALkJrhh4ycBYDU95Skmh2NICjKFdueiTrA

上面的页面似乎是翻译:

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;
        }
}

我将继续努力提供有关此代码如何工作的解释,并在将来将它们添加到此答案中。