strStr()、文字列照合を実装する-Java

strStr()関数を実装します。

干し草の山の文字列と針の文字列が与えられた場合、干し草の山の文字列内の針の文字列の最初の位置を見つけます(0から開始)。存在しない場合は-1を返します。

例1:
入力:haystack = "hello"、needle = "ll"
出力:2

例2:
入力:haystack = "aaaaa"、needle = "bba"
出力:-1

説明:
針が空の文字列の場合、どの値を返す必要がありますか?これはインタビューの良い質問です。
この質問では、針が空の文字列の場合は0を返す必要があります。これは、C言語のstrstr()およびJavaのindexOf()の定義と一致しています。

ソース:LeetCodeリンク:https://leetcode-cn.com/problems/implement-strstr

方法1:部分文字列を1つずつ比較します

最も簡単な方法-スライディングウィンドウを文字の変更に沿って段階的に移動し、ウィンドウ内の部分文字列を針の文字列と比較します。
ここに画像の説明を挿入します

public static int strStr(String haystack, String needle) {
    
    
    int L = needle.length(), n = haystack.length();

    for (int start = 0; start < n - L + 1; ++start) {
    
    
        if (haystack.substring(start, start + L).equals(needle)) {
    
    
            return start;
        }
    }
    return -1;
}

方法2:ダブルポインター

前の方法の欠点は、干し草の山の長さLのすべての部分文字列が針の文字列と比較されることですが、これは実際には不要です。
まず、比較が必要になるのは、部分文字列の最初の文字が針文字列の最初の文字と同じである場合のみです
ここに画像の説明を挿入します
次に、文字ごとに比較でき、一致しない場合はすぐに終了します。
ここに画像の説明を挿入します
次の図に示すように、最後のビットを比較すると不一致が検出され、バックトラックが開始されます。pnポインタはpn = pn-curr_lenの位置ではなくpn = pn-curr_len +1の位置に移動することに注意してください。
ここに画像の説明を挿入します
このとき、再度比較して完全に一致する部分文字列を見つけ、部分文字列の開始位置pn-Lを直接返します。
ここに画像の説明を挿入します

アルゴリズム

  • pnが指す位置の文字が針の文字列の最初の文字と等しくなるまで、pnポインタを動かします。
  • pn、pL、およびcurr_lenを使用して一致する長さを計算します。
  • 完全に一致する場合(つまり、curr_len == L)、一致した部分文字列の開始座標を返します(つまり、pn-L)。
  • 正確に一致しない場合は、バックトラックします。pn = pn-curr_len + 1、pL = 0、およびcurr_len = 0とします。
public static int strStr2(String haystack, String needle) {
    
    
    //needle和haystack的长度
    int L = needle.length(), n = haystack.length();
    if (L == 0) return 0;

    //haystack当前的指针索引
    int pn = 0;
    while (pn < n - L + 1) {
    
    
        //在haystack字符串中找到与needle字符串第一个字符相等的字符的位置
        while (pn < n - L + 1 && haystack.charAt(pn) != needle.charAt(0)) pn++;

        //计算最大匹配字符串
        int currLen = 0;//匹配的长度
        int pL = 0;//needle当前的指针索引
        //通过 pn,pL,curr_len 计算匹配长度
        while (pL < L && pn < n && haystack.charAt(pn) == needle.charAt(pL)) {
    
    
            pn++;
            pL++;
            currLen++;
        }

        //如果needle字符串被找到,返回needle字符串出现的第一个位置
        if (currLen == L) return pn - L;

        //否则,回滚pn
        pn = pn - currLen + 1;
    }
    return -1;
}

おすすめ

転載: blog.csdn.net/m0_46390568/article/details/107525656