匹配字符串中的子集

时间:2010-10-14 17:01:51

标签: java string

假设我有 -

String x = "ab";
String y = "xypa";

如果我想查看y中是否存在x的任何子集,那么最快的方法是什么?循环耗时。在上面的例子中,x的子集是“a”,它在y中找到。

8 个答案:

答案 0 :(得分:2)

答案真的取决于许多事情。

如果你只是想找到任何子集而你只做了一次,那么循环就可以了(并且你可以做到最好而不需要使用额外的存储空间),你可以在找到它时停下来匹配的单个字符。

如果您有一个固定的x,并希望将其用于匹配多个字符串y,则可以执行一些预处理,将x中的字符存储在表格中并使用此表格用于检查y中的每个字符是否出现在x中。

如果您想找到最大子集,那么您正在查看另一个问题:longest common subsequence problem

答案 1 :(得分:1)

嗯,我不确定它比循环更好,但你可以使用String#matches

if (y.matches(".*[" + x + "]+.*")) ...

您需要转义正则表达式[]构造中特殊的字符(例如]-\,...)。< / p>

以上只是一个示例,如果您不止一次这样做,则需要使用PatternMatcher以及java.util.regex package中的其他内容。

答案 2 :(得分:0)

循环很耗时,但除了重复遍历目标字符串之外,没有办法做你想做的事。

您可以做的是先通过检查最小的字符串进行优化,然后逐步提升。例如,如果目标字符串不包含abc,则它不可能包含abcdef

我的其他优化:

  • 在匹配不匹配的字符后不要继续检查匹配,但在Java中,您可以让计算机担心这一点。
  • 如果目标字符串中没有足够的字符可以匹配,请不要检查某些内容是否匹配。
  • 如果您需要速度并且有足够的空间,您可以将目标字符串分解为像trie这样的奇特数据结构以获得更好的结果,尽管我没有准确的算法
  • 另一个存储不是问题的解决方案:将目标分解为每个可能的子字符串,并将结果存储在HashSet中。

答案 3 :(得分:0)

你必须使用for循环或使用与for循环一样昂贵的正则表达式,因为你需要将你的一个字符串基本上转换为字符。

Boolean isSubset = false;
for(int i = 0; i < x.length(); i++) {
        if(y.contains(x.charAt(i))) {
                isSubset = true;
                break;
        }
}

使用for循环。

答案 4 :(得分:0)

看起来这可能是longest common substring problem的情况。

答案 5 :(得分:0)

你可以生成x的所有子集(例如,在你的例子中,ab,a,b),然后生成一个可以执行

的正则表达式
  Pattern p = Pattern.compile("(ab|a|b)");
  Matcher m = p.matcher(y);
  if(m.find()) {
    System.err.println(m.group());
  }

答案 6 :(得分:0)

如果两个字符串只包含[a-z]。然后最快的是制作两个位图,26位长。标记字符串中包含的所有位。获取位图的AND,结果位出现在两个字符串中,这是最大的公共子集。这将是一个简单的O(n),其中n是最大字符串的长度。

(如果你想覆盖整个UTF,布隆过滤器可能更合适。)

答案 7 :(得分:0)

这个怎么样??

package so3935620;

import static org.junit.Assert.*;

import java.util.BitSet;

import org.junit.Test;

public class Main {

  public static boolean overlap(String s1, String s2) {
    BitSet bs = new BitSet();
    for (int i = 0; i < s1.length(); i++) {
      bs.set(s1.charAt(i));
    }
    for (int i = 0; i < s2.length(); i++) {
      if (bs.get(s2.charAt(i))) {
        return true;
      }
    }
    return false;
  }

  @Test
  public void test() {
    assertFalse(overlap("", ""));
    assertTrue(overlap("a", "a"));
    assertFalse(overlap("abcdefg", "ABCDEFG"));
  }
}

如果该版本太慢,您可以根据s1计算BitSet,将其保存在某个变量中,稍后只循环s2