减少字符串数组中序列的最佳方法

时间:2008-09-11 16:10:38

标签: c# .net algorithm

请现在我已经重新编写了这个问题,在它被fast-gun answers进一步eager editors或过早关闭之前,请允许我指出这不是{{3}的副本。 }}。我知道如何从数组中删除重复项。

这个问题是关于从数组中删除序列,而不是严格意义上的重复。

考虑数组中的这个元素序列;

[0] a
[1] a
[2] b
[3] c
[4] c
[5] a
[6] c
[7] d
[8] c
[9] d

在这个例子中,我想获得以下内容......

[0] a
[1] b
[2] c
[3] a
[4] c
[5] d

请注意,保留了重复的元素,但同一元素的序列已被简化为该元素的单个实例。

此外,请注意,当两行重复时,它们应缩减为一组(两行)。

[0] c
[1] d
[2] c
[3] d

......减少到......

[0] c
[1] d

我在C#编码,但任何语言的算法都很受欢迎。

4 个答案:

答案 0 :(得分:2)

编辑:做了一些更改和新建议

滑动窗口怎么样......

REMOVE LENGTH 2: (no other length has other matches)
//the lower case letters are the matches
ABCBAbabaBBCbcbcbVbvBCbcbcAB  
__ABCBABABABBCBCBCBVBVBCBCBCAB

REMOVE LENGTH 1 (duplicate characters):
//* denote that a string was removed to prevent continual contraction
//of the string, unless this is what you want.
ABCBA*BbC*V*BC*AB
_ABCBA*BBC*V*BC*AB

RESULT:
ABCBA*B*C*V*BC*AB == ABCBABCVBCAB

这当然从length = 2开始,将其增加到L / 2并向下迭代。

我也在考虑另外两种方法:

  1. digraph - 使用数据设置有状态有向图并使用字符串迭代它,如果找到一个循环,则会有重复。我不确定检查这些周期是多么容易...可能是一些动态编程,所以它可能与下面的方法2相当。我将不得不考虑这个更长的时间。
  2. 距离矩阵 - 使用levenstein距离矩阵,您可能能够检测到对角线移动(离开对角线)的重复,成本为0.这可能表示数据重复。我将不得不考虑更多。

答案 1 :(得分:1)

我会将它们全部转储到您最喜欢的Set实现中。

编辑:既然我理解了这个问题,那么您的原始解决方案就是最好的方法。只需循环遍历数组一次,保持一组标志以标记要保留的元素,加上一个计数器以跟踪新数组的大小。然后再次循环以将所有守护者复制到新阵列。

答案 2 :(得分:1)

这是我写的C#app解决了这个问题。

<强>取
aabccacdcd

<强>输出
abcacd

可能看起来很乱,带我一点点动态模式长度位。

class Program
{
    private static List<string> values;
    private const int MAX_PATTERN_LENGTH = 4;

    static void Main(string[] args)
    {
        values = new List<string>();
        values.AddRange(new string[] { "a", "b", "c", "c", "a", "c", "d", "c", "d" });


        for (int i = MAX_PATTERN_LENGTH; i > 0; i--)
        {
            RemoveDuplicatesOfLength(i);
        }

        foreach (string s in values)
        {
            Console.WriteLine(s);
        }
    }

    private static void RemoveDuplicatesOfLength(int dupeLength)
    {
        for (int i = 0; i < values.Count; i++)
        {
            if (i + dupeLength > values.Count)
                break;

            if (i + dupeLength + dupeLength > values.Count)
                break;

            var patternA = values.GetRange(i, dupeLength);
            var patternB = values.GetRange(i + dupeLength, dupeLength);

            bool isPattern = ComparePatterns(patternA, patternB);

            if (isPattern)
            {
                values.RemoveRange(i, dupeLength);
            }
        }
    }

    private static bool ComparePatterns(List<string> pattern, List<string> candidate)
    {
        for (int i = 0; i < pattern.Count; i++)
        {
            if (pattern[i] != candidate[i])
                return false;
        }

        return true;
    }
}

修复了初始值以匹配问题值

答案 3 :(得分:0)

我同意如果您可以将字符串转储到Set中,那么这可能是最简单的解决方案。

如果由于某种原因无法访问Set实现,我只会按字母顺序对字符串进行排序,然后执行一次并删除重复项。如何对列表进行排序并从列表中删除重复项取决于您运行代码的语言和环境。

编辑:哦,ick ....我根据你的澄清看到你预计甚至可以在单独的行上发生模式。我的方法不会解决你的问题。抱歉。这是给你的问题。如果我有以下文件。

B'/ P>

C

C

B'/ P>

C

C

您希望它简化为

吗?

B'/ P>

C