匹配数组

时间:2016-07-13 22:09:12

标签: java string algorithm

假设我有以下输入,我的实现语言是Java:

  • 一个数组 A ,内容为:["brown fox", "jumped over the", "lazy dog", "dog", "the", "fish", "quantum burrito", "ox jumped over the laz", "and ate", "ate pie"]

  • 字符串 S ,内容为:"the quick brown fox jumped over the lazy dog and ate pie"(第一个字符索引0,最后一个字符索引55)

我需要(在典型的计算机上尽可能有效)组装字符串 S 的子字符串列表,这些子字符串(完全)包含在数组 A <的元素中/ em>,并按降序获取。我还需要知道每个匹配的字符串 S 中的起始和结束字符索引。 ......但有一些限制。

以下限制和特性适用于此问题:

  • 并非数组 A 中的所有元素都可以包含在字符串 S 中(在示例中,&#34; fish&#34;和&#34;量子burrito&#34;不在 S )。
  • 字符串 S 可能包含与数组中任何元素不匹配的字符长度(在示例中,&#34;快速&#34;在 S A 中的任何内容都不匹配。
  • 尊重 S 中的字边界 A 中的确切一个空格保证单词分隔 S );意思是,如果 S 中的字符长度与 A 匹配,则匹配但是通过不捕获一个或多个来违反字边界整句话
  • 如果长度为平局,则结果数组中的排序顺序无关紧要。
  • 一旦 S 中的一系列字符匹配,该范围将仅在一个结果元素中捕获,即使它可以匹配 A 中的多个元素。
  • 如果有两个可能的匹配,请根据算法处理数组中元素的顺序任意选择一个。
  • 我需要跟踪算法完成后哪些字符范围不匹配。

只需查看字符串和数组即可手动执行此操作,在此示例中,解决方案如下,以正确的降序(从零开始索引)给出:

  1. 字符范围[20..34](&#34;跳过&#34;)位于数组的索引1中。长度= 15
  2. 字符范围[10..18](&#34;棕色狐狸&#34;)位于数组的索引0中。长度= 9
  3. 字符范围[36..43](&#34;懒狗&#34;)位于数组的索引2中。长度= 8
  4. 字符范围[49..55](&#34;吃馅饼&#34;)位于数组的索引9中(任意匹配;匹配&#34;并且ate&# 34;同样有效,但我们不匹配两者因为&#34; ate&#34;已经&#34;消费&#34 ;;没有双关语意图)。长度= 7
  5. 字符范围[0..2](&#34;&#34;)位于数组的索引4中。长度= 3
  6. 这个词&#34;快速&#34;与数组中的任何元素都不匹配。
  7. &#34;和&#34;与数组中的任何元素都不匹配。
  8. 特别注意,&#34; ox跳过laz&#34;虽然它是 A S 中最长的子串,但是<结果集中匹配强>不,因为它违反了&#34; fox&#34;和&#34;懒惰&#34;。

    问题:我是否描述了一个可能存在于库中的相当标准的算法(部分或全部;我愿意用更简单的原始构建块来构建它)或者是这样的我需要从头开始实现自定义吗?

    如果我从头开始实施,我认为我需要采取如下概括的方法:

    • 在字边界上拆分字符串 S
    • 按降序长度顺序构造字符串 S 中所有(顺序尊重)单词序列的列表 L (例如:["the quick brown fox jumped over the lazy dog and ate pie", "the quick brown fox jumped over the lazy dog and ate", "quick brown fox jumped over the lazy dog and ate pie", ... "the quick brown fox jumped", ... "brown fox jumped", ... "jumped", "quick", "brown", ... "pie"])。
    • 从数组 A 的内容构建后缀树 T
    • 按顺序遍历列表 L ,并尝试查找 T
    • 中的每个元素
    • 找到元素后,记下 S 的子字符串范围, A 的匹配索引,然后继续迭代
    • 每次匹配一个元素时,如果元素的字符范围索引与已匹配的元素重叠,则跳过它并继续

    听起来很慢......而且可能中等难以做好。

1 个答案:

答案 0 :(得分:1)

您可以轻松地单独使用正则表达式。虽然以下是说明性的,并且不符合广泛的请求列表(即将结果放入数组并对其进行排序),但这些请求很容易实现。

“棘手”部分是字边界分隔符 \b 并使用群组 ()来捕获您想要的实际群组想要匹配。

String[] A = {"brown fox", "jumped over the", "lazy dog", "dog", "the", "fish", "quantum burrito", "ox jumped over the laz", "and ate", "ate pie"};
String S = "the quick brown fox jumped over the lazy dog and ate pie";

for(String s : A) {
    Pattern p = Pattern.compile(".*\\b(" +s+ ")\\b.*");
    Matcher m = p.matcher(S);

    while (m.find()) {
        System.out.println(m.matches() + " => " + s);
        System.out.println("    Start index: " + m.start(1));
        System.out.println("    End index: " + m.end(1));
        System.out.println("    Length: " + m.group(1).length());
    }
}

上面匹配所有包含的字符串,只要它们是空格分隔的,并在主字符串中输出它们的开始/结束位置。