【问题标题】:Implementing Java's indexOf method (Substring search)实现 Java 的 indexOf 方法(子字符串搜索)
【发布时间】:2016-08-02 04:19:40
【问题描述】:

我只是第二学期的 CS 学生,不能使用任何众所周知的高效子字符串搜索算法。我需要使用以下方法签名来实现 indexOf 方法:

int indexOf(String str, String pattern) 返回模式作为 str 的子字符串出现的第一个位置的索引。

这是我尝试的:

首先,我创建了一个重载方法索引,其签名为 indexOf(String str, char ch, int startIndex),它返回 char 的第一个位置的索引,否则返回 -1。

 private int indexOf(String str, char ch, int startIndex) {
    for(int i = startIndex; i < str.length(); i++)
        if(str.charAt(i) == ch) return i;

    return -1;
}

现在我编写搜索子字符串 (pattern) 的方法。

private int indexOf(String str, String pattern) {
    int headIndex = indexOf(str, pattern.charAt(0), 0);
    int tailIndex = indexOf(str, pattern.charAt(pattern.length() - 1), 0);

    if(headIndex == -1 || tailIndex == -1) return -1; // no substring match

    while(true) {
        int j = 0;
        for(int i = headIndex; i <= tailIndex; i++)
            if(str.charAt(headIndex) != pattern.charAt(j++)) { //if substring does not match then compute a new head and tail Index
                headIndex = indexOf(str, pattern.charAt(0), headIndex);
                tailIndex = indexOf(str, pattern.charAt(pattern.length() - 1), tailIndex);
                j = 0;
                i = headIndex + 1;
                if(headIndex == -1 || tailIndex == -1) return -1;
                break;
            }

        if(headIndex >= 0) return headIndex;
    }
}

我相信我已经接近了,但像 indexOf("Hellolo", "lo") 这样的调用返回 2 而不是 3。我正试图找出我的逻辑哪里出了问题并需要帮助。

我不允许使用任何特殊的字符串方法,除了长度。

【问题讨论】:

  • 可能是因为索引是从 0 而不是 1 开始的?
  • “不能使用任何众所周知的高效子串搜索算法”是否意味着您不能使用现有的实现,或者您必须使用未知且效率低下的算法?
  • @AndyTurner 不能使用像 Boyer-Moore 这样的现有实现
  • 我认为您的逻辑有些复杂。要实现简单的O(mn) 算法,我认为您不需要(第一个)indexOf(String, char, int) 方法。
  • 如果您更新 headIndextailIndex 并从现有的 headIndextailIndex 值开始调用 indexOf 辅助方法,您将得到相同的值(您在你的 for 循环中重新执行此操作)。尝试从每个索引的下一个索引开始,看看你会得到什么。

标签: java string algorithm substring indexof


【解决方案1】:

在您的代码中,您正在寻找单个字符而不是字符串的第一个索引。

int headIndex = indexOf(str, pattern.charAt(0), 0);

如果我们假设str = Hellolo"pattern = "lo",那么上面的代码正在寻找l 而不是lo

编辑:如果要查找字符串"lo" 的第一次出现,则必须将代码更改为

int headIndex = indexOf(str, pattern, 0);

【讨论】:

  • 但这就是我想要实现的方法
  • 这不是你所拥有的@MutatingAlgorithm。
【解决方案2】:

indexOf("Hellolo", "lo") 返回 2,因为计数是从零开始的... 这里是doc

public int indexOf(int ch)

返回此字符串中第一次出现的索引 指定的字符。如果一个值为 ch 的字符出现在 此 String 对象表示的字符序列,然后是索引 (在 Unicode 代码单元中)第一次出现的此类事件被返回。为了 ch的值在0到0xFFFF(含)的范围内

【讨论】:

  • 但即使计数为 0,它仍应返回索引位置 3
【解决方案3】:

我只是以尽可能简单的方式编写代码。

package com.ggl.testing;

public class MyString {

    public static void main(String[] args) {
        MyString myString = new MyString();
        String string = "abcdefghij";
        String pattern = "defg";
        System.out.println(myString.indexOf(string, pattern));

        pattern = "ghij";
        System.out.println(myString.indexOf(string, pattern));

        pattern = "asdf";
        System.out.println(myString.indexOf(string, pattern));
    }

    public int indexOf(String string, String pattern) {
        int length = string.length() - pattern.length();
        for (int index = 0; index <= length; index++) {
            if (patternMatch(string, index, pattern)) {
                return index;
            }
        }

        return -1;
    }

    private boolean patternMatch(String string, int index, String pattern) {
        int i = index;
        for (int j = 0; j < pattern.length(); j++) {
            if (string.charAt(i) != pattern.charAt(j)) {
                return false;
            }
            i++;
        }

        return true;
    }

}

【讨论】:

  • patternMatch 如果您在 for 循环声明中声明并增加 i (或仅使用 index + j 代替)会更容易。
【解决方案4】:
int headIndex = indexOf(str, pattern.charAt(0));
int tailIndex = indexOf(str, pattern.charAt(pattern.length() - 1));

if(headIndex == -1 || tailIndex == -1) return -1; // no substring match

Buggy -> 考虑这种情况:

String str = "nevern";
String pattern = "vern";

我认为专注于头部字符就足够了:

public class Search {


    static private int indexOf(String src, char ch, int startIndex) {
        for(int i = startIndex; i < src.length(); i++)
            if(src.charAt(i) == ch) return i;

        return -1;
    }

    static private int indexOf(String src, String pat) {
        int head_in_src = 0;

        while (-1 != (head_in_src = indexOf(src, pat.charAt(0), head_in_src))) {
            if (head_in_src + pat.length() > src.length() - head_in_src)
                return -1;
            boolean match = true;
            int offset = 0;
            for (; offset < pat.length(); offset++) {
                if (src.charAt(offset + head_in_src) != pat.charAt(offset)) {
                    match = false;
                    break;
                }
            }
            if (true == match)
                return head_in_src;
            head_in_src += offset;
        }
        return -1;
    }

    public static void main(String[] args) {
        String src = "ne-nevern-nevern";
        String pat = "ever";
        String pat1 = "ne";
        String pat2 = "vern";
        String pat3 = "everne";
        String pat4= "-ne-";
        String pat5= "ner";

        System.out.printf("src=%1$s, pat=%2$s, index=%3$d%n", src, pat, indexOf(src, pat));
        System.out.printf("src=%1$s, pat1=%2$s, index=%3$d%n", src, pat1, indexOf(src, pat1));
        System.out.printf("src=%1$s, pat2=%2$s, index=%3$d%n", src, pat2, indexOf(src, pat2));
        System.out.printf("src=%1$s, pat3=%2$s, index=%3$d%n", src, pat3, indexOf(src, pat3));
        System.out.printf("src=%1$s, pat4=%2$s, index=%3$d%n", src, pat4, indexOf(src, pat4));
        System.out.printf("src=%1$s, pat5=%2$s, index=%3$d%n", src, pat5, indexOf(src, pat5));
    }
}

输出:

src=ne-nevern-nevern, pat=ever, index=4
src=ne-nevern-nevern, pat1=ne, index=0
src=ne-nevern-nevern, pat2=vern, index=5
src=ne-nevern-nevern, pat3=everne, index=-1
src=ne-nevern-nevern, pat4=-ne-, index=-1
src=ne-nevern-nevern, pat5=ner, index=-1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    相关资源
    最近更新 更多