PHP 字符串匹配算法 Sunday算法


搜索文本 text = "my testing algorithm in test"

模式 pattern = "test"

Sunday算法的關鍵點在於

1.設定一個匹配位移映射 shift[],這個shift[]映射關系必須按從左到右的順序簡歷,例如pattern = "test",注意到此處有2個t,那么建立出來的位移映射是 shift[] = Array ( [t] => 1 [e] => 3 [s] => 2 ),而如果不是從左到右,是從右到左的建立映射,就會變成 shift[] = Array ( [t] => 4 [e] => 3 [s] => 2),這樣到時候匹配就無法得到正確結果

2.根據當前比對字符串的下一個字符來確定位移長度,如下圖

第一次比較的時候,如圖1,第一個字符“m”就和“t”不一樣,那就查找比patter長1位的text中的字符,為“e”,然后查找映射表,e => 3,接下來把pattern向后移動3位,就到了,圖2中的位置,再從“t”開始比較,發現匹配到了繼續往后,看text中比pattern長1的那個字符,為“i”,此時發現映射表中沒有“i”,則直接將pattern向后移動pattern_size位,就到了圖3,然后重復前面的過程,直到比較到text_size - patter_size為坐標的那個字符

 

下面是代碼:

 1 <?php
 2     #字符串匹配,sunday算法
 3     
 4     function sunday($patt, $text) {
 5         $patt_size = strlen($patt);
 6         $text_size = strlen($text);
 7 
 8         #初始化字符串位移映射關系
 9         #此處注意,映射關系表的建立一定是從左到右,因為patten可能存在相同的字符
10         #對於重復字符的位移長度,我們只能讓最后一個重復字符的位移長度覆蓋前面的位移長度
11         #例如pattern = "testing",注意到此處有2個t,那么建立出來的位移映射是 shift[] = Array ( [t] => 4 [e] => 6 [s] => 5 [i] => 3 [n] => 2 [g] => 1 )
12         #而如果不是從左到右,是從右到左的建立映射,就會變成 shift[] = Array ( [t] => 7 [e] => 6 [s] => 5 [i] => 3 [n] => 2 [g] => 1 ),這樣到時候匹配就無法得到正確結果
13         for ($i = 0; $i < $patt_size; $i++) {
14             $shift[$patt[$i]] = $patt_size - $i;
15         }
16 
17         $i = 0;
18         $limit = $text_size - $patt_size; #需要開始匹配的最后一個字符坐標
19         while ($i <= $limit) {
20             $match_size = 0; #當前已匹配到的字符個數
21             #從i開始匹配字符串
22             while ($text[$i + $match_size] == $patt[$match_size]) {
23                 $match_size++;
24                 if ($match_size == $patt_size) {
25                     echo "Match index: {$i} <br>";
26                     break;
27                 }
28             }
29 
30             $shift_index = $i + $patt_size; #在text中比pattern的多一位的字符坐標
31             if ($shift_index < $text_size && isset($shift[$text[$shift_index]])) {
32                 $i += $shift[$text[$shift_index]];
33             } else {
34                 #如果映射表中沒有這個字符的位移量,直接向后移動patt_size個單位
35                 $i += $patt_size;
36             }
37         }
38     }
39 
40     $text = "my testing algorithm test";
41     $patt = "test";
42 
43     sunday($patt, $text);
44 ?>

 

 

Match index: 3 
Match index: 21


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM