如何检查String是否包含任何顺序的子字符串?

时间:2015-01-27 10:04:57

标签: java string substring

这与&#34不同;如何检查字符串是否包含特定的子字符串?" 。我发现这里没有类似的问题,但不是我想要的。 我在竞争性编码网站上创建了一个程序,其中的问题是我们给出了一个由x,y,z组成的字符串,我们必须计算包含至少一个字符但不是全部字符串的子字符串的数量。我试过这个......

    String text = sc.next();
      int l = text.length();
      int count=0;
     for(int j =1;j<=l;j++)
      {
     for(int i1 =0;i1<j;i1++){
        String g = text.substring(i1,j);
        if(g.contains("xyz")||g.contains("xzy")||g.contains("yzx")||g.contains("yxz")||g.contains("zxy")||g.contains("zyx"))
        ;
        else
        count++;




      }

      }
      System.out.println(count);

这有效(至少2个测试用例)。但对于较大的测试用例,我的程序违反了时间限制。现在我认为这是因为if子句中匹配条件的数量。我想知道是否有任何方法可以检查子串是否包含&#39; xyz&#39;以任何顺序而不是检查每个订单。谢谢!任何帮助表示赞赏。

P.S-如果还有其他因素违反时限,请提及!

1 个答案:

答案 0 :(得分:0)

这是一个简单的解决方案。警告未经测试的代码!

String target = ...

String text = sc.next();
if (target.length() == 0) {
    // matched!
} else {
    for (int i = 0; i <= text.length() - target.length(); i++) {
        if ((pos = target.indexOf(text.charAt(i))) >= 0) {
            boolean[] found = new boolean[target.length()];
            found[pos] = true;
            int matchCount = 1;
     outer: for (j = 1; j < target.length(); j++) {
                pos = 0;
                while (true) {
                    pos = target.indexOf(text.charAt(i + j), pos);
                    if (pos == -1) {
                       break outer;
                    } else if (!found[pos]) {
                       found[pos] = true;
                       matchCount++;
                       break;
                    }
                }
            }
            if (matchCount == target.length()) {
                // matched!
            }
        }
    }
}

如果你想更快地做到这一点,一种可能性就是清除并回收我们正在使用的found数组&#34;标记&#34;我们匹配的角色。

可能会有更重要的优化。但是,我不认为Boyer-Moore&#34;技巧&#34;跳过一些人物将在这里工作。

<强>更新

您的原始解决方案是O(N factorial(M)),其中N是文本长度,M是目标字符串长度。

我的解决方案是O(N M)

最佳解决方案涉及通过乘以素数来计算运行哈希值,如How to find all permutations of a given word in a given text?的答案之一所述。我认为它平均为O(N)

(提示:我所指的解决方案看起来像是O(M N)。但是,我们应该能够使用逆乘法等式:

  

((ab mod n)。(b -1 mod n))mod n = a mod n

其中ab是主要因素,n是2 32 或2 64 ,具体取决于我们是否使用intlong。参考:wikipedia

这将允许&#34;乘以&#34;然后&#34;反向乘法&#34;字符,因此更新O(1)操作中的运行哈希值。)