【轉載】https://blog.csdn.net/LEE18254290736/article/details/77278769算法
對於正常的字符串模式匹配,主串長度爲m,子串爲n,時間複雜度會到達O(m*n),而若是用KMP算法,複雜度將會減小線型時間O(m+n)。數組
設主串爲ptr="ababaaababaa";,要比較的子串爲a=「aab」;spa
KMP算法用到了next數組,而後利用next數組的值來提升匹配速度,我首先講一下next數組怎麼求,以後再講匹配方式。.net
next數組詳解blog
首先是理解KMP算法的第一個難關是next數組每一個值的肯定,這個問題困惱我很長時間,尤爲是對照着代碼一行一行分析,很容易把本身繞進去。ip
定義一串字符串字符串
ptr = "ababaaababaa";get
next[i](i從1開始算)表明着,除去第i個數,在一個字符串裏面從第一個數到第(i-1)字符串前綴與後綴最長重複的個數。string
什麼是前綴?it
在「aba」中,前綴就是「ab」,除去最後一個字符的剩餘字符串。
同理能夠理解後綴。除去第一個字符的後面所有的字符串。
在「aba」中,前綴是「ab」,後綴是「ba」,那麼二者最長的子串就是「a」;
在「ababa」中,前綴是「abab」,後綴是「baba」,兩者最長重複子串是「aba」;
在「abcabcdabc」中,前綴是「abcabcdab」,後綴是「bcabcdabc」,兩者最長重複的子串是「abc」;
這裏有一點要注意,前綴必需要從頭開始算,後綴要從最後一個數開始算,中間截一段相同字符串是不行的。
再回到next[i]的定義,對於字符串ptr = "ababaaababaa";
next[1] = -1,表明着除了第一個元素,以前前綴後綴最長的重複子串,這裏是空 ,即"",沒有,咱們記爲-1,表明空。(0表明1位相同,1表明兩位相同,依次累加)。
next[2] = -1,即「a」,沒有前綴與後綴,故最長重複的子串是空,值爲-1;
next[3] = -1,即「ab」,前綴是「a」,後綴是「b」,最長重複的子串「」;
next[4] = 1,即"aba",前綴是「ab」,後綴是「ba」,最長重複的子串「a」;next數組裏面就是最長重複子串字符串的個數
next[5] = 2,即"abab",前綴是「aba」,後綴是「bab」,最長重複的子串「ab」;
next[6] = 3,即"ababa",前綴是「abab」,後綴是「baba」,最長重複的子串「aba」;
next[7] = 1,即"ababaa",前綴是「ababa」,後綴是「babaa」,最長重複的子串「a」;
next[8] = 1,即"ababaaa",前綴是「ababaa」,後綴是「babaaa」,最長重複的子串「a」;
next[9] = 2,即"ababaaab",前綴是「ababaaa」,後綴是「babaaab」,最長重複的子串「ab」;
next[10] = 3,即"ababaaaba",前綴是「ababaaab」,後綴是「babaaaba」,最長重複的子串「aba」;
next[11] = 4,即"ababaaabab",前綴是「ababaaaba」,後綴是「babaaabab」,最長重複的子串「abab」;
next[12] = 5,即"ababaaababa",前綴是「ababaaabab」,後綴是「babaaaababa」,最長重複的子串「ababa」;
還有另一種方法,我看的有的書上寫着:
這裏咱們定義next[1] = 0 , next[1] = 1;
再分析ptr字符串,ptr = "ababaaababaa";
跟上一個的狀況相似,
next[1] = 0 ,事先定義好的
next[2] = 1 ,事先定義好的
next[3] = 1 ,最長重複的子串「」;1表明沒有重複,2表明有一個字符重複。
next[4] = 2 ,最長重複的子串「a」;追償的長度加1,即爲2.
next[5] = 3 ,如下都跟以前的同樣,這種方法是最長的長度再加上一就能夠了。
next[6] = 4
next[7] = 2
next[8] = 2
next[9] = 3
next[10] = 4
next[11] = 5
next[12] = 6
以上是next數組的詳細解釋。next數組求值 是比較麻煩的,剩下的匹配方式就很簡單了。
next數組用於子串身上,根據上面的原理,咱們可以推出子串a=「aab」的next數組的值分別爲0,1,2.(按照我說的第二種方式算的)。
首先開始計算主串與子串的字符,設置主串用i來表示,子串用j來表示,若是ptr[i]與a[i]相等,那麼i與j就都加1:
prt[1]與a[1]相等,i++,j++:
用代碼實現就是
ptr[2]與a[2]不相等
此時ptr[2]!=a[2],那麼令j = next[j],此時j=2,那麼next[j] = next[2] = 1.那麼此時j就等於1.這一段判斷用代碼解釋的話就是:
加上上面的代碼進行組合:
在對兩個數組進行比對時,各自的i,j取值代碼:
此時將a[j]置於j此時所處的位置,即a[1]放到j=2處,由於在j=2時出現不匹配的狀況。
此時再次計算是否匹配,能夠看出來a[1]!=ptr[2],那麼j = next[j],即此時j = next[1] = 0;
根據上面的代碼,當j=0時,執行++i;++j;
此時就變爲:
此時ptr[3] = a[1],繼續向下走,下一個又不相等了,而後「aab」向後挪一位,這裏再也不贅述了,主要的思想已經講明白了。到最後一直到i = 8,j=3時匹配成功,KMP算法結束。整個過程就結束了。