數據結構-BF算法及KMP算法

BF算法

代碼

<?php
function bf($s,$t){
    $i=0;
    $j=0;
    $k;
    while($i<strlen($s) && $j<strlen($t)){
        if($s[$i] == $t[$j]){
            $i++;
            $j++;

        }else{
            $i = $i - $j + 1;
            $j = 0;;
        }
        
    }    
    if($j >= strlen($t)) $k = $i - strlen($t);
    else $k = -1;
    return $k;    
}
$str1 = "abaabcabclkjlkff";
$str2 = "abc";
echo bf($str1,$str2);
?>

複雜度

最壞狀況的時間複雜度O(m*n)。m爲模式串長度。n爲目標串長度。php

KMP算法

代碼

<?php
function GetNext($t,&$next){
    $j = 0;
    $k = -1;
    $next[0] = -1;
    while($j<strlen($t)){
        if($k==-1||$t[$j] == $t[$k]){
            $j++;
            $k++;
            $next[$j]=$k;
        }
        else $k = $next[$k];
    }
//    var_dump($next);
}
function KMPIndex($s,$t){
    $i = 0;
    $j = 0;
    $v;
    $next = [];
    GetNext($t,$next);
//    var_dump($next);
    while($i<strlen($s) && $j<strlen($t)){
        if($j==-1 || $s[$i]==$t[$j]){
            $i++;
            $j++;
        }else{
            $j = $next[$j];
        }
    }
    if($j>=strlen($t)) $v = $i - strlen($t);
    else $v = -1;
    return $v;
}

$s="ababcabcacbab";
$t="abcac";
$k;
$k = KMPIndex($s,$t);
echo $k;
?>

時間複雜度

時間複雜度爲O(m+n)。m爲模式串長度。n爲目標串長度。
算法簡單記憶分爲兩步:1.模式串掃描,生成next數組,O(m)。2.主串掃描,匹配,O(n)。
KMP算法對BF算法的回溯問題進行了改進,在整個匹配過程當中對主串僅需從頭到尾掃描一遍。java

其餘

  1. php函數參數傳遞。在定義函數時在參數前加上'&'改成引傳遞。通常狀況爲值傳遞,對象除外。算法

  2. php在字符串索引某個字符。若包含中文字符須要另行處理。js能夠經過"[]"直接索引。java用charat函數。數組

  3. BM算法。函數

思考

看一個生成next數組的簡單例子。
考慮模式串t="abab",觀察一下next數組的生成過程。指針

  1. 初始化。j=0 k=-1 next[0]=-1code

  2. 第一趟。j=1 k=0 next[1]=0對象

  3. 第二趟。k=next[0]=-1索引

  4. 第三趟。j=2 k=0 next[2]=0字符串

  5. 第四趟。匹配。j=3 k=1 next[3]=1

  6. 第五趟。匹配。j=4 k=2 next[4]=2

這裏首先能夠注意到在第六步中j=4,而實際在咱們的模式串"abab"中4這個下標已經越界了,嗯嗯,不要着急,咱們先來看看在每一趟循環中到底作了什麼。

if($k==-1||$t[$j] == $t[$k]){
            $j++;
            $k++;
            $next[$j]=$k;
        }
        else $k = $next[$k];

代碼不過5行,一個if...else...的判斷語句。假設看的同窗已經在其餘地方看過這裏先後綴的原理了。
若是k=-1或t[j]=t[k],j++,k++,next[j]=k。
這裏的k=-1暫時不考慮他的做用,那麼就是若是主串(模式串)與子串中的字符匹配,則主串指針向後一位,子串指針向後一位,給next數組賦值。
不然k=next[k]。不然向前移動子串指針。這裏也是根據next數組移動子串指針而且須要注意抽象出子串的概念。

因此在第六步中匹配成功之後主串子串移動,在這以後已經跳出循環了。而實際上next[4]在目標串中匹配是用不到的。

嗯。。要記住是先嚐試匹配,成功後在向後移動指針,不匹配則重置指針。

這裏的k=-1能夠理解爲當首位不匹配時移動指針的一個條件。

緊接着能夠思考模式串"abcab","abcabd","ababab"等next數組的生成過程。理解kmp的重點在於next數組是如何生成的。

相關文章
相關標籤/搜索