next[j]表示當前模式串T的j下標對目標串S的i值失配時,咱們應該使用模式串的下標爲next[j]接着去和目標串失配的i值進行匹配
咱們能夠知道next除了j=1時,next[1]爲0,其餘狀況都是比較前綴和後綴串的類似度(第三種狀況是當類似度爲0時,next值爲0+1=1)
next數組,是用來評判先後綴的相識度,而next值,則是等於類似度加一
雖然咱們知道是比較先後綴的類似度,可是咱們如何肯定先後綴位置來獲取next值。---->pj的next值取決於 前綴p1p2....pk-1 後綴pj-k+1.....pj-1 的類似度,next值是類似度加一
pj的next值取決於 前綴p1p2....pk-1 後綴pj-k+1.....pj-1 的類似度,是類似度加一。 咱們將k-1=m,其中m就是類似度,k就是next數組值-->Max{K} pj的next值取決於 前綴p1p2....pm 後綴pj-m.....pj-1 的類似度,是類似度加一。
那麼咱們如今的任務,就由找k-1變爲找m,找類似度
例如:
雖然咱們能夠直接看出abab的類似度是2,
也能夠編寫函數獲取到其類似度,
並且當咱們求下一個next值時,串變爲ababa,這時咱們也能夠看出類似度爲3,使用同一個函數能夠實現獲取到類似度。
可是咱們這個函數大概就是從頭或尾開始索引,進行判斷。
每次咱們獲取到了子串都要交給這個函數從頭至尾去索引獲取類似度,彷佛不划算,咱們是否是應該有更好的方法增長程序的性能?
next數組,是用來評判先後綴的相識度,而next值,則是等於類似度加一
next[j]表示當前模式串T的j下標對目標串S的i值失配時,咱們應該使用模式串的下標爲next[j]接着去和目標串失配的i值進行匹配
注意:匹配完畢後後綴會向下加一
重點:這個m值取決於上次失配時的next[]值,即上次j=3是失配了,全部m=next[3]=1,因此咱們選取的前綴爲p1='a',後綴爲pj-1是'a'
根據匹配處的類似度或者下標J=1均可以得出next[4]=2
重點:如果上次匹配成功。並未失配,那麼咱們的m值在上一次的基礎上加1。因此此次m=2,咱們選取前綴p1p2和後綴p3p4
根據匹配處的類似度或者下標J=2均可以得出next[5]=3
由於前面匹配成功,全部m++,m=3因此前綴爲p1p2p3,後綴爲p3p4p5
根據匹配處的類似度或者下標J=3均可以得出next[6]=4
根據匹配處的類似度或者下標J=1均可以得出next[7]=2
因爲上面失配了,因此m=next[7]=2,匹配前綴p1p2,和後綴p6p7
根據匹配處的類似度或者下標J=1均可以得出next[8]=2
因爲上面失配了,因此m=next[8]=2,因此咱們前綴爲p1p2,後綴爲p7p8
根據匹配處的類似度或者下標J=2均可以得出next[9]=3
另外一種方案:是直接看匹配位置的j值便可,將j值加一便可,這個是實現程序的時候的使用思路
注意:有可能模式串只有一個字符進行匹配,那麼咱們以前說的next[2]=1也須要咱們去匹配一遍,而不是直接獲取結果
咱們以上圖爲例:
類似度是指前綴串和後綴串之間的類似程度,經過看圖,咱們不難發現類似度和最後匹配的下標使同樣的。
這是由於前綴始終是如下標爲一的字符開始匹配,因此匹配到下標爲多少,那他的類似度就是多少
//經過計算返回子串T的next數組 void get_next(String T, int* next) { int m, j; j = 1; //j是後綴的末尾下標 pj-m...pj-1 其實j-1就是後綴的下標,而j就是咱們要求的next數組下標 m = 0; //m表明的是前綴結束時的下標,也就是類似度,是等價的 p1p2...pm next[1] = 0; while (j < T[0]) //T[0]是表示串T的長度 {
//這個if,咱們只須要考慮,若是我<後綴最後下標>前面匹配成功,如今我T[j]==T[m]也匹配成功,那麼我對應的next<++j>數組值是多少? if (m == 0 || T[m] == T[j]) //T[m]表示前綴的最末尾字符,T[j]是後綴的最末尾字符 { ++m; ++j; next[j] = m; //++j後獲取的纔是咱們要的next[j]下標,咱們要獲取next[j]處的值,就是獲取他前一個匹配時的類似度,也就是前一個匹配的下標+1 } else //else是匹配失敗的狀況,就要進行回溯 m = next[m]; //如果字符不相同,則m回溯 } }
int main() { int i; String s1; int next[MAXSIZE] = { 0 }; char *str = (char*)malloc(sizeof(char) * 40); memset(str, 0, 40); printf("enter s1:"); scanf("%s", str); if (!StrAssign(s1, str)) printf("1.string length is gt %d\n", MAXSIZE); else printf("1.string StrAssign success\n"); get_next(s1, next); for (i = 1; i <= StringLength(s1); i++) printf("%d ", next[i]); system("pause"); return 0; }