【问题标题】:String pattern search algorithm stack overflow字符串模式搜索算法堆栈溢出
【发布时间】:2016-12-14 17:21:22
【问题描述】:

我正在尝试将this code 修改为递归版本,以提高执行时间效率。代码所做的是在 Text 中查找所有模式的第一个索引并将它们添加到 ArrayList。我的代码如下:

public boolean search(String text, int n, String pattern, int d) {
    if (n > text.length() || n < d) return true;
    while (d >= 0 && d < pattern.length() && n < text.length() && text.charAt(n) != pattern.charAt(d)) d = next[d];
    if (d == pattern.length()) {
    (***) if (ans == null || !ans.contains(n-d)) ans.add(n-d);                    
          n = n-d;
          d = -1;
    }
    if( n < text.length() && n >= d ) search(text, n+1, pattern, d+1);
    return false;
}

我的代码的循环版本:

public void search(String text) {
int m = this.pattern.length();
int n = text.length();
int i, j;
for (i = 0, j = 0; i < n && j < m; i++) {
    while (j >= 0 && text.charAt(i) != this.pattern.charAt(j)) {
        j = next[j];
    }
    j++;
    if (j >= m) {
    if (ans == null || !ans.contains(i-m+1) ) ans.add(i-m+1);     
        j = 0;
        i = i - m + 1;
    }
}}

更糟糕的是,它是指数级的,这就是我无法满足时间限制的原因。

数组next[] 与示例代码相同。我的问题是:

  1. 当参数文本字符串变大时,比如超过 2200 个字符,它总是引发java.lang.StackOverflowError;特别是在括号内的三个星号的行中。即使只剩下ans.add(n-d),仍然是同样的问题。返回值boolean 毫无意义,即使我将函数return 类型更改为void 并删除最后一行,它仍然是同样的问题。

  2. 有没有更好的方法来做到这一点?

【问题讨论】:

  • 是什么让您认为递归版本会更高效?它所能做的就是更慢。正如消息所说,您会遇到堆栈溢出(由于大量递归)。最好保留原代码。
  • 感谢 Yves Daoust 的回复。通过使用最后第二个条件,我不必一直走到字符串末尾并在 n
  • 原代码的一个问题是它总是超过时间限制,另一个是它只能得到一个模式索引,我需要在Text中找到所有模式的索引。
  • 大部分代码对返回值没有影响,一旦超过第一个 if,返回值总是 false。
  • @TaoWang:使代码递归没有帮助。如果你想加速算法,看看经典的解决方案。en.wikipedia.org/wiki/String_searching_algorithm

标签: java string algorithm pattern-matching trie


【解决方案1】:

目前 JVM (Hotspot) 没有尾调用优化。所以每次递归都会消耗栈。所以你得到stackoverflow错误。目前最好坚持迭代方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多