正则表达式找到所有子串和最长子串

时间:2011-07-10 23:03:10

标签: c# java regex

我通常会使用字符串库来做这样的事情。但我想知道是否可以使用正则表达式来完成。

我想执行以下操作:给定搜索字符串

  

西雅图很棒

我想在给定的句子中找到它的所有子串。因此,将正则表达式应用于以下句子

  

西雅图西雅图非常棒,令人敬畏的是西雅图

应该给我

  

西雅图,西雅图很棒,很棒,很棒,是,西雅图

一个可能有用的约束是句子总是只有搜索字符串中的单词和中间的空格。

注意如果匹配,则应该是最长的字符串。因此,与上面的示例一样,匹配不应该是单个单词而是最长的子串。还需要保持单词之间的顺序。这就是为什么

  很棒的是西雅图

上面的句子中的

给了我们

  

太棒了,是和西雅图

我不确定这样的事情是否可以通过正则表达式完成,因为它是贪婪的。非常感谢对此的任何见解! 我熟悉C#和Java,可以使用他们的任一个正则表达式库。

4 个答案:

答案 0 :(得分:3)

我认为你不能用正则表达式做到这一点。维基百科有一篇关于longest common subsequence problem的好文章。

答案 1 :(得分:2)

用正则表达式直接表达这样的模式没有好办法。

您需要列出所有允许的组合:

Seattle is awesome|Seattle is|Seattle|is awesome|is|awesome

或更简洁:

Seattle( is( awesome)?)?|is( awesome)?|awesome

您可以通过编程方式将输入字符串转换为此格式。

答案 2 :(得分:0)

你能进一步描述一下你的问题吗?它听起来更像是一个搜索引擎,而不是简单的字符串匹配。我强烈建议查看Apache Lucene - 它有一点学习曲线,但它是一个很好的智能搜索工具。它处理许多在处理搜索时遇到的问题。您可以设置命中评分,使其完全符合您的描述。

答案 3 :(得分:0)

在Java中,未经过测试。这将返回字符串列表上的迭代器。每个列表都是匹配的子序列。 只需在列表成员之间放置空格即可打印。如果使用很多,使用intern()可能会很糟糕。

static Iterator<List<String>> getSequences(String squery, String starget)
{
    List<String> query = Arrays.asList(squery.split(" "));
    for ( int i = 0; i < query.size(); i++)
        query.set(i, query.get(i).intern());
    List<String> target = Arrays.asList(starget.split(" "));;
    for ( int i = 0; i < target.size(); i++)
        target.set(i, target.get(i).intern());

    // Because the strings are all intern'ed, this HashSet acts like we want -
    // If two lists are the same sequence of words, they are equal.
    // It's used to remove duplicates.
    HashSet<List<String>> ret = new HashSet<List<String>>();
    for ( int qBegin = 0; qBegin < query.size(); qBegin++ )     {
        for ( int tBegin = 0; tBegin < target.size(); tBegin++ ) {
            for ( int iCursor = 0; 
                  iCursor < min(query.size()-qBegin, target.size()- tBegin); 
                  iCursor++)                {
                if ( query.get(qBegin+iCursor)==target.get(tBegin+iCursor) )
                    ret.add(query.subList(qBegin, qBegin+iCursor+1));
                else break;
            }
        }
    }
    return ret.iterator();
}

static int min(int a, int b) { return (a<b)? a:b; }