仅使用linq的最长重复序列

时间:2019-03-28 21:36:09

标签: c# linq lcs lrs

正如标题所述,我有一个任务来查找字符串中最长的重复序列,并且只能使用linq完成-否ifs,不循环,不尝试,赋值仅允许在变量初始化时进行,递归是允许的。我已经在网上找到了解决方案,并且我了解发生了什么,但是我无法将其转换为linq-我对此并不熟悉。如果有人可以帮助我,我将不胜感激。这是我找到的-https://www.javatpoint.com/program-to-find-longest-repeating-sequence-in-a-string的链接。

List<int> a = new List<int> {1, 2, 1, 2, 1, 2, 3, 2, 1, 2};
List<List<int>> aa = new List<List<int>>();
outerLoop(a);

var max = aa.Max(x => x.Count);
var m = from v in aa 
    where v.Count == max
    select v;
    m.Dump();

void outerLoop(List<int> list)
{
List<int> f = new List<int>();
f.AddRange(list.Skip(list.Count-1).Take(list.Count).ToList());
innerLoop(list, list.Skip(1).Take(list.Count).ToList());

f.ForEach(k => outerLoop(list.Skip(1).Take(list.Count).ToList()));
}


void innerLoop(List<int> l, List<int> subList)
{
List<int> f = new List<int>();
f.AddRange(subList.Skip(subList.Count-1).Take(subList.Count).ToList());
var tt = l.TakeWhile((ch, i) => i < subList.Count && subList[i] == ch).ToList();

aa.Add(tt);
f.ForEach(k => innerLoop(l, subList.Skip(1).Take(subList.Count).ToList()));
}

所以我想出了这个“美”,我认为它不是很好的代码,但我认为它可以工作。如果有人有兴趣并想提出改善建议,欢迎他们::

如果输入为int[] x= {1, 2, 1, 2, 1, 2, 3, 2, 1, 2} 结果应该是1212

2 个答案:

答案 0 :(得分:0)

尝试一下:

List<int> words = new List<int> { 1, 2, 1, 2, 1, 2, 3, 2, 1, 2 };

string result =
    words
        .Select((c, i) => i)
        .SelectMany(i => Enumerable.Range(1, words.Count - i).Select(j => words.Skip(i).Take(j)), (i, w) => new { i, w })
        .GroupBy(x => String.Join(",", x.w), x => x.i)
        .Where(x => x.Skip(1).Any())
        .Select(x => x.Key)
        .OrderByDescending(x => x.Length)
        .First();

那给了我1,2,1,2

如果您想要一个真正适用于字符串的字符串,请尝试以下操作:

var word = "supercalifragilisticexpialidocious";

string result =
    word
        .Select((c, i) => i)
        .SelectMany(i => Enumerable.Range(1, word.Length - i).Select(j => word.Skip(i).Take(j)), (i, w) => new { i, w })
        .GroupBy(x => new string(x.w.ToArray()), x => x.i)
        .Where(x => x.Skip(1).Any())
        .Select(x => x.Key)
        .OrderByDescending(x => x.Length)
        .First();

那给了我ali


这是一个稍微容易理解的版本:

var word = "supercalifragilisticexpialidocious";

string result =
(
    from i in Enumerable.Range(0, word.Length)
    from j in Enumerable.Range(1, word.Length - i)
    group i by word.Substring(i, j) into gis
    where gis.Skip(1).Any()
    orderby gis.Key.Length descending
    select gis.Key
).First();

答案 1 :(得分:0)

这是我的版本。它不是单个LINQ表达式,但仅使用LINQ。如果有多个答案,它将返回所有相同长度的子序列。它应该适用于任何类型的序列。它被编写为仅使用标准的LINQ方法。

它使用带有字符串键的GroupBy来实现序列Distinct。 (由于这个技巧,包含逗号的项目列表可能无法正常工作。)在生产代码中,对于基于Distinct的序列,我将使用IEqualityComparerSequenceEqual。在生产代码中,我将使用MaxBy扩展名。它还有一个单独的步骤,用于找到最大重复序列长度,然后找到所有匹配的序列。

更新:由于我在GroupBy中使用DistinctBy,所以我意识到我可以使用它直接计算子序列重复数,而不必搜索它们。

var repeaters = Enumerable.Range(0, words.Count) // starting positions
                       .SelectMany(n => Enumerable.Range(1, (words.Count - n) / 2).Select(l => words.Skip(n).Take(l).ToList())) // subseqs from each starting position
                       .GroupBy(s => String.Join(",", s), (k, sg) => new { seq = sg.First(), Repeats = sg.Count() }) // count each sequence
                       .Where(sr => sr.Repeats > 1) // only keep repeated sequences
                       .Select(sr => sr.seq); // no longer need counts
var maxRepeaterLen = repeaters.Select(ss => ss.Count()).Max(); // find longest repeated sequence's length
var maxLenRepeaters = repeaters.Where(ss => ss.Count() == maxRepeaterLen); // return all sequences matching longest length