-3

正如标题所说,我的任务是在字符串中找到最长的重复序列,并且只能使用 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

4

2 回答 2

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();
于 2019-03-29T00:06:38.783 回答
0

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

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

更新:由于我使用GroupByfor 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
于 2019-03-29T18:51:30.923 回答