【问题标题】:Prefer jagged arrays over multidimensional [closed]比多维更喜欢锯齿状数组[关闭]
【发布时间】:2014-09-15 16:09:58
【问题描述】:

我从 Visual Studio (Prefer jagged arrays over multidimensional) 得到了这个性能问题。
要替换的代码是“//矩阵”。
我怎样才能用我的代码做到这一点?

      public static int LevenshteinDistance(string s, string t)
    {
        int n = s.Length; //length of s
        int m = t.Length; //length of t

        int[,] d = new int[n + 1, m + 1]; // matrix

        int cost; // cost
        // Step 1
        if (n == 0) return m;
        if (m == 0) return n;
        // Step 2
        for (int i = 0; i <= n; d[i, 0] = i++) ;
        for (int j = 0; j <= m; d[0, j] = j++) ;
        // Step 3
        for (int i = 1; i <= n; i++)
        {
            //Step 4
            for (int j = 1; j <= m; j++)
            {
                // Step 5
                cost = (t.Substring(j - 1, 1) == s.Substring(i - 1, 1) ? 0 : 1);
                // Step 6
                d[i, j] = System.Math.Min(System.Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
                          d[i - 1, j - 1] + cost);
            }
        }
        // Step 7
        return d[n, m];
    }

【问题讨论】:

  • 那么你的问题是什么?
  • @Servy 我的问题是,如何将数组转换为锯齿状数组。 “int[,] d = 新的 int[n + 1, m + 1];” --> ?
  • 您对如何创建锯齿状数组进行了哪些研究,在实施研究中发现的解决方案时遇到了哪些问题?
  • "我遇到了这个性能问题" 是什么让您相信性能问题与将数据表示为多维非锯齿状数组有关?据我所知,这是一个不平凡的算法,所以我期望表示支配它的时间。
  • 在这个非常特殊的情况下,您可以使用 2 个一维数组(参见 Levenshtein distance,使用两个矩阵行迭代)而不是二维数组来实现 Levenshtein 距离。这将空间需求从 n*m 减少到 n+m,并且您不需要使用多维数组。

标签: c# multidimensional-array jagged-arrays


【解决方案1】:

这是一个只使用一维数组的版本。

public static int LevenshteinDistance(string s, string t)
{
    int n = s.Length; //length of s
    int m = t.Length; //length of t

    int stride = m+1;
    int[] d = new int[(n + 1)*stride];
    // note, d[i*m + i + j] holds (i,j)

    int cost;
    // Step 1
    if (n == 0) return m;
    if (m == 0) return n;
    // Step 2, adjusted to skip (0,0)
    for (int i = 0, k = stride; k < d.Length; k += stride) d[k] = ++i;
    for (int j = 1; j < stride; ++j) d[j] = j;
    // Step 3
    int newrow = stride * 2;
    char si = s[0];
    for (int i=0, j=0, k = stride + 1; k < d.Length; ++k)
    {
        // don't overwrite d[i,0]
        if (k == newrow) {
            newrow += stride;
            j=0;
            si=s[++i];
            continue;
        }

        // Step 5
        cost = (t[j] == si ? 0 : 1);

        // Step 6
        d[k] = System.Math.Min(System.Math.Min(
             d[k-stride] + 1, /* up one row */
             d[k-1] + 1       /* left one */   ),
             d[k-stride-1] + cost /* diagonal */ );
    }

    // Step 7
    return d[d.Length-1];
}

这应该通过 3 种方式提高性能:

  • 没有字符串比较,也没有一个字符串垃圾供 GC 清理
  • 更改了内存布局以匹配迭代顺序,改进了缓存行为
  • 使用一维数组和优化器友好的惯用语,应该减少边界检查

但是,我很确定应用 mike z 的使用两个向量的建议将使代码更加清晰。

【讨论】:

猜你喜欢
  • 2018-11-04
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
相关资源
最近更新 更多