【问题标题】:How to check if a String contains a substring in any order? [duplicate]如何检查字符串是否包含任何顺序的子字符串? [复制]
【发布时间】:2015-03-25 21:44:06
【问题描述】:

这与“如何检查字符串是否包含特定子字符串?”不同。 .我在这里没有发现这样的问题,但不是我要找的。 我正在一个竞争性编码站点上创建一个程序,该程序的问题表明我们得到了一个由 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 子句中匹配条件的数量。我想知道是否有任何方法可以检查子字符串是否以任何顺序包含“xyz”,而不是检查每个订单。谢谢!任何帮助表示赞赏。

P.S- 如果有其他原因导致违反时限,请务必提及!

【问题讨论】:

  • 时间问题来自于您使用的是二次解决方案,其中包含两个嵌套的 for 循环。这种类型的解决方案需要 O (n^2) 时间,而需要更好的解决方案。
  • 请发布一些带有等待结果的输入字符串
  • 输入字符串来自所有案例都经过测试的输入文件!我现在无法发布它们,因为我现在可以访问我的笔记本电脑。我稍后会提供。至于现在,您能否提供嵌套 for 循环的替代方案? @lamsomeone &
  • 其实这个解大概是O(n^3),因为contains方法大概是O(n)线性搜索。
  • 您正在将此输入拆分为非常小的部分 (text.substring(i1,j);)。你为什么不在全文上尝试你的 contains 方法,这将为你节省很多迭代。

标签: java string substring


【解决方案1】:

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

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 数组,以便在匹配字符时“标记”这些字符。

可能会有更重要的优化。但是,我认为 Boyer-Moore 跳过多个字符的“技巧”在这里行不通。

更新

您的原始解决方案是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 是 232 或 264 取决于我们使用的是 int 还是 @987654335 @。参考:wikipedia.

这将允许“乘入”然后“逆乘出”字符,因此更新O(1) 操作中的运行哈希。)

【讨论】:

  • 抱歉,我正在寻找最佳解决方案!您的解决方案也包含一个嵌套的 for。所以这也可能违反时间限制!
  • @KirtyBhushan - 如果没有 2 个 for 循环,您将无法获得 最佳 解决方案。一个循环遍历整个字符串,另一个循环检查子字符串的排列。就这么简单
  • @KirtyBhushan - 然后随意优化它:-)
  • 我明白了!我也试图在没有嵌套循环的情况下得到答案,但没有成功!但是,我也可以通过其他人发布的解决方案!我正在尝试自己做任何事情!无论如何,感谢您的帮助。我会尝试找到一个最佳的解决方案。
  • @KirtyBhushan - 可以尝试的一个选项是回溯/递归。或者使用 indexOflastIndexOf() 减小输入大小。但最坏的情况,好吧。什么都做不了
猜你喜欢
  • 2011-03-29
  • 2015-03-24
  • 2019-06-07
  • 1970-01-01
  • 2018-08-25
  • 2020-09-20
  • 2011-11-09
  • 2013-05-18
  • 1970-01-01
相关资源
最近更新 更多