<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          KMP算法(字符串匹配)

          共 2307字,需瀏覽 5分鐘

           ·

          2022-02-14 11:36


          字符串匹配是常見的算法題,就有一個(gè)字符串判斷里面是否包含另一個(gè)字符串。


          舉例來說,有一個(gè)字符串"AAAAAABC"(主串),我想知道,里面是否包含另一個(gè)字符串"AAAB"(模式串)?對主串和模式串做匹配。



          首先,字符串 "AAAAAABC" 的第一個(gè)字符與搜索詞 "AAAB" 的第一個(gè)字符,進(jìn)行比較。

          AAAAAABCAAAB


          字符串有一個(gè)字符與搜索詞的第一個(gè)字符相同,接著比較字符串和搜索詞的下一個(gè)字符,還是相同。直到字符串有一個(gè)字符,與搜索詞對應(yīng)的字符不相同為止。


          當(dāng)字符串的索引為 3 的時(shí)候發(fā)現(xiàn)不相等,這時(shí),最自然的反應(yīng)是,將搜索詞整體后移一位,再從頭逐個(gè)比較。


          AAAAAABC AAAB


          基于這個(gè)想法我們可以得到以下的程序:

          function bf(ts, ps) {  let t = ts;  let p = ps;  let i = 0; // 主串的位置  let j = 0; // 模式串的位置  while (i < t.length && j < p.length) {    if (t[i] === p[j]) { // 當(dāng)兩個(gè)字符串相同,就比較下一個(gè)      i++;      j++;    } else {      i = i - j + 1; // 一旦不匹配,i后退      j = 0; // j歸0    }  }  if (j === p.length) {    return i - j  } else {    return -1;  }}
          console.log(bf('AAAAAABC', 'AAAB'))


          上面的程序是沒有問題的,但不夠好!這是暴力解法復(fù)雜度 O(nm) 的。這太慢了!



          我們很難降低字符串比較的復(fù)雜度(因?yàn)楸容^兩個(gè)字符串,真的只能逐個(gè)比較字符)。因此,我們考慮降低比較的趟數(shù)。


          跳過不可能成功的字符串比較


          有些趟字符串比較是有可能會(huì)成功的;有些則毫無可能。而如果我們跳過那些絕不可能成功的字符串比較,則可以希望復(fù)雜度降低到能接受的范圍。



          一個(gè)基本事實(shí)是,當(dāng) d 不匹配時(shí),你其實(shí)知道前面五個(gè)字符是"abcab"。如果是人為來尋找的話,肯定不會(huì)再把 i 移動(dòng)到索引為1,我們會(huì)直接移動(dòng)到索引為3!就可以來到第二個(gè)"ab"的位置。


          所以,整個(gè)KMP的重點(diǎn)就在于當(dāng)某一個(gè)字符與主串不匹配時(shí),我們應(yīng)該知道指針要移動(dòng)到哪?


          移動(dòng)位數(shù) = 已匹配的字符數(shù) - 對應(yīng)的部分匹配值


          首先,要了解兩個(gè)概念:"前綴"和"后綴"。"前綴"指除了最后一個(gè)字符以外,一個(gè)字符串的全部頭部組合;"后綴"指除了第一個(gè)字符以外,一個(gè)字符串的全部尾部組合。


          "abcab"的前綴為[a, ab, abc, abca],后綴為[bcab, cab, ab, b],共有元素為"ab",長度為2;


          "部分匹配"的實(shí)質(zhì)是,有時(shí)候,字符串頭部和尾部會(huì)有重復(fù)。比如,"abcab"之中有兩個(gè)"ab",那么它的"部分匹配值"就是2("ab"的長度)。搜索詞移動(dòng)的時(shí)候,第一個(gè)"ab"向后移動(dòng)到索引為3(字符串長度5-部分匹配值2),就可以來到第二個(gè)"ab"的位置。


          根據(jù)nxt數(shù)組加快字符串匹配。

          function getNext(p) {  let nxt = [];  nxt.push(0); // next[0] 必然是0  let x = 1; // 因此 nxt[1] 開始求  let now = 0;  while (x < p.length) {    if (p[now] === p[x]) { // 如果 p[now] == p[x] ,則可以向右擴(kuò)展一位      now += 1      x += 1      nxt.push(now)    } else if (now) {      now = nxt[now - 1] // 縮小 now,改成 nxt[now - 1]    } else {      nxt.push(0) // now 已經(jīng)為0,無法再縮小了, 故 nxt[x] = 0      x += 1    }  }  return nxt}
          console.log(getNext('abcab'))// [ 0, 0, 0, 1, 2 ]


          根據(jù)nxt數(shù)組移動(dòng)標(biāo)尺。

          function bf(ts, ps)  let t = ts;  let p = ps;  let i = 0; // 主串的位置  let j = 0; // 模式串的位置  let nxt = getNext(ps)  while (i < t.length && j < p.length) {    if (t[i] === p[j]) { // 當(dāng)兩個(gè)字符串相同,就比較下一個(gè)      i++;      j++;    } else {      // 失配了      if (j) {        j = nxt[j - 1] // 根據(jù)nxt數(shù)組移動(dòng)標(biāo)尺      } else {        i++; // ps[0]失配了,直接把標(biāo)尺往右移動(dòng)一位      }    }  }  if (j === p.length) {    return i - j  } else {    return -1;  }}


          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91福利影院 | 亚洲婷婷成人激久久月天 | 国产黄色片网站 | 午夜人妻精品理论片中文字幕 | 亚洲黄级aaa |