如何在字符串中找到所有可能的子串?

11

我想做的是取一个字符串并返回所有长度大于2的可能子串。所以,使用welcome这个例子:

we
el
lc
co
me
wel
elc
lco
com
ome
welc
elco
lcom
come
and so on.....

我能想到的唯一方法是像这样(未经测试):

for (int i = 0; i < word.Length; i++) //i is starting position
{
   for (int j = 2; j + i < word.Length; j++) //j is number of characters to get
   {
       wordList.Add(word.SubString(i, j));
   }
}

但我想知道是否有更好的方法来做到这一点(可能使用LINQ),而我不知道?


2
这正是我会做的方式...不过,你不想从零开始吗? - jahroy
这对于第一个循环是正确的。我需要测试以确保其余部分,但我认为由于我不想要1个字母的子字符串,所以我需要从2开始。 - Abe Miessler
1
你可能还想在 wordList 中检查唯一性?例如,如果你的字符串是“mememe”,那么子字符串“me”会出现多次。 - RJ Lohan
@RJ Lohan,你说的独一无二的观点很好。由于这个应用程序的整体情况,我可能会在使用 Distinct() 创建整个单词列表之后再进行此操作。 - Abe Miessler
2
我认为你的代码有一个错误 - 内部循环需要在 j+i <= word.Length 时终止。 - RJ Lohan
显示剩余2条评论
3个回答

15

这个方法看起来简单易懂,怎么样?

var text = "welcome";

var query =
    from i in Enumerable.Range(0, text.Length)
    from j in Enumerable.Range(0, text.Length - i + 1)
    where j >= 2
    select text.Substring(i, j);

它会产生:

we 
wel 
welc 
welco 
welcom 
welcome 
el 
elc 
elco 
elcom 
elcome 
lc 
lco 
lcom 
lcome 
co 
com 
come 
om 
ome 
me 

1
如果你让第二个.Range2开始,就可以摆脱where - AakashM
@AakashM - 我当然可以通过将第二个“Range”更改为“Enumerable.Range(2,text.Length-i-1)”来删除“where j> = 2”,但这会使此查询的功能不太明显。它会短路一些迭代,但它都在内存中,并且无论哪种方式都非常快。 - Enigmativity

4
这个LINQ解决方案应该可以工作:
var str = "welcome";
var items = Enumerable
    .Range(0, str.Length)
    .SelectMany(i => Enumerable.Range(2, str.Length-i-1).Select(j => str.Substring(i, j)))
    .Distinct()
    .OrderBy(s => s.Length);
foreach (var s in items) {
    Console.WriteLine(s);
}

1
嗯...这就是我发现基于循环的方法更清晰易读的地方 :-) 虽然 Linq 可以解决这个问题,但它不像基于循环的方法那样易读(这是 Linq 的一个强项之一)。 - Hao
1
@Hao 当然可以!使用LINQ解决这么简单的问题只是为了证明LINQ足够强大,纯属好奇。 - Sergey Kalinichenko

0
代码如下:
   internal static List<string> GetAllSubstring(String mainString)
    {
        try
        {
            var stringList = new List<string>();
            if(!string.IsNullOrEmpty(mainString))
            {
                for (int i = 0; i < mainString.Length; i++) //i is starting position
                {
                    for (int j = 2; j + i < mainString.Length; j++) //j is number of characters to get
                    {
                        if(!stringList.Contains(mainString.Substring(i, j)))
                        {
                            stringList.Add(mainString.Substring(i, j));
                        }
                    }
                }

            }

            return stringList;
        }
        catch(Exception ex)
        {

        }

        return null;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接