字串匹配演算法【未完待續】

ajiang02發表於2020-01-21

題目:

給定兩個字串 A 和 B,請判斷 B 是否是 A 的子串,是的話返回 B 在 A 中第一次出現的位置。

例子:

字串 A(主串):abbcefgh
字串 B(模式串):bce
B 在 A 中第一次出現的位置是 2(從0開始)

暴力演算法(Brute Force)

BF 演算法是從頭開始,把主串和模式串的字元一個一個進行匹配。如果發現不匹配,再從主串的下一位開始。

<?php
namespace app\index\controller;

class Index 
{
    /**
     * 時間複雜度 O(mn)
     */
    public function brute_force()
    {
        $main_string    = 'abbcefgh';                // 主串
        $pattern_string = 'bce';                     // 模式串
        $main_len       = strlen($main_string);      // 主串長度
        $pattern_len    = strlen($pattern_string);   // 模式串長度
        $index          = null;                      // 匹配的位置

        // 迴圈主串
        for ($i = 0; $i < $main_len; $i++) {
            // 迴圈模式串
            for ($j = 0; $j < $pattern_len; $j++) {
                // 如果模式串當前字元 != 主串當前字元,則沒必要比較模式串後面的字元,進入下一個主串字元
                if ($main_string[$i + $j] != $pattern_string[$j]) {
                    break;
                }
                // 如果模式串的全部字元匹配,則記錄位置
                if ($j == $pattern_len - 1) {
                    $index = $i;
                }
            }
        }
        echo $index;
    } 
}

RK 演算法(Rabin-Karp)

RK 演算法是暴力演算法的改進。
暴力演算法對兩個字串的所有字元依次比較,而 RK 演算法比較的是兩個字串的 雜湊值

<?php
namespace app\index\controller;

class Index extends TestCase
{
    /**
     * 時間複雜度 O(n)
     */
    public function RK()
    {
        $main_string    = 'abbcefgh';                // 主串
        $pattern_string = 'bce';                     // 模式串
        $main_len       = strlen($main_string);      // 主串長度
        $pattern_len    = strlen($pattern_string);   // 模式串長度
        $index          = null;                      // 匹配的位置
        $pattern_hash   = hash('md5', $pattern_string, false);       // 模式串的hash值

        // 迴圈主串,每次擷取模式串長度的子串,取其hash值,與模式串hash值比較
        for ($i = 0; $i <= $main_len - $pattern_len; $i++) {
            $interception      = substr($main_string, $i, $pattern_len);              // 擷取主串的子串
            $interception_hash = hash('md5', $interception, false);  // 取子串的hash值

            // 如果 hash值相等,記錄當前主串的位置
            if (hash_equals($interception_hash, $pattern_hash)) {
                $index = $i;
            }
        }
        echo $index;
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章