題目:
給定兩個字串 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 協議》,轉載必須註明作者和本文連結