零零散散學演算法之再敘字串匹配

2021-09-06 09:50:32 字數 2953 閱讀 3330

出自:

字串匹配問題這是個老話題了,而我們也熱衷於學習和**這個問題,並且我們也經常會用到它。比如說,我們用vim開啟乙個文字檔案,要在這個檔案中查詢某乙個字串時,我們只需在底行模式下輸入/string即可;再比如,在linux終端中,我們要把當前目錄下所有的c檔案列印出來,那麼這時候我們就會利用正規表示式來進行匹配操作(所有的c檔案可表示為*.c),而不是挨個去找。

其二:對於乙個演算法愛好者,如一位仁兄所說:say what you think and show your code!如若這樣,豈不快哉!

我為什麼叫它固定串呢?我還是舉個例子說明一下吧(沒辦法,語言表達能力不好啊)!假設有源字串…superfcing…,我們想知道子串superfc是否在源串中出現過?此時不難看出子串是乙個確定的字串(不含有不確定的字元),那麼我就將它成為固定字串匹配法。

解決這種情況的演算法不用我多說,自然是kmp演算法(最壞情況為o(strlen(source_string) + k))了。對於這個演算法先前也說過,在這就不細說了。這個演算法的關鍵步驟就是源串字首陣列的生成。下面我用圖例給出字首陣列的生成過程:

對於kmp演算法,歸總起來就是:掃瞄源字串,更新並標記子串在源串中出現的位置。

附註:關於kmp演算法的字首函式,當陣列的起始下標為0時,務必不要讓字首函式的初值設為0,如果這樣的話,可能會死迴圈。你如果對此有興趣,自己可以試試。

好了,固定串匹配的情況就是這樣,解決方法也有了,接下來我們看看**的實現:

**中使用到的變數代表的含義:

[html]view plain

copy

print?

/*  source:源串  

**  sourcelength:源串長度  

**  prefix:字首陣列  

**  pattern:匹配串,即子串  

**  p_length:子串長度  

**  buffer:當源串中有子串匹配時,用buffer儲存這些子串  

*/<

span

style="font-size:18px;"

>

span

>

[cpp]view plain

copy

print?

/**為kmp演算法得到字首陣列**/

void getprefixarray(char *source, int *prefix, int sourcelength)  

if(source[k] == source[i])  

prefix[i] = k;  

}  }  

[cpp]view plain

copy

print?

void stringmatchofkmp(char *source, int sourcelength, int *prefix,  

char *pattern, int p_length, char *buffer)  

if(source[i] == pattern[j])  

if(j == p_length)  

i++;  

}  }  

所謂單字元動態匹配,就是:當字串中出現?字元時,該字元表示匹配任意的乙個字元(因為它是任意的乙個字元,所以說它是單字元動態匹配)。那麼這種情況怎麼解決呢?很簡單,我們只需要對源串做一次遍歷,並不需要像固定串匹配那樣利用kmp演算法。即子串在匹配源串的過程中,當遇見?字元時,我們直接認為子串中的該字元和源串中對應位置的字元匹配成功。舉個例子,假設源串為hellosuperfc,子串為s*per,那麼當源串和子串中的s匹配時,分別做++,這個時候源串中的u就會和子串中的*相比較,此時我們就認為*就是字元u,匹配成功,然後進行下乙個字元的匹配。

好,給個圖示:

單字元動態匹配就是這樣,我們來看看它的實現**:

[cpp]view plain

copy

print?

void stringmatchofask(char *source, int sourcelength, char *pattern,  

int p_length, char *buffer)  

else

}  else

}  }  

所謂多字元動態匹配,就是:當子串中出現*字元時,該字元表示可以匹配至少0個以上的字元(因為它可以匹配多個字元,所以說它是多字元動態匹配)。那麼這種情況怎麼解決呢?我認為它比單字元動態匹配還要簡單,即當子串中的*與源串中的對應字元比較時,我就認為*字元包含從源串中的當前位置開始,直到當子串中的下乙個字元與源串中的字元相等時,匹配結束。這麼說太拗口了,我用乙個圖例來說明一下:

我們來看看**的實現:

[cpp]view plain

copy

print?

void stringmatchofstar(char *source, int sourcelength, char *pattern,  

int p_length, char *buffer)  

/*儲存起始匹配的下標*/

if(0 == j - 1)  

}  else

if(pattern[j] == '*')  

i++;  

}  }  

零零散散學演算法之詳解幾種最短路徑

深入解析最短路徑演算法 正文第一節 問題的提出及解決方法 所謂最短路徑問題,可以說有兩種情況來描述。描述一 在圖論中,指的是尋找圖中兩個節點之間的最短距離。如下圖 描述二 在現實生活中,指的是找到從乙個地方到另乙個地方的最近距離。如下圖 上述兩種情況的本質是一樣的,即求乙個點到另乙個點的最短路徑。好...

零零散散學演算法之具體解釋幾種最短路徑

深入解析最短路徑演算法 正文第一節 問題的提出及解決方法 所謂最短路徑問題,能夠說有兩種情況來描寫敘述。描寫敘述一 在圖論中,指的是尋找圖中兩個節點之間的最短距離。例如以下圖 描寫敘述二 在現實生活中,指的是找到從乙個地方到還有乙個地方的近期距離。例如以下圖 上述兩種情況的本質是一樣的,即求乙個點到...

演算法之 字串匹配演算法

一說到兩個字串匹配,我們很自然就會想到用兩層迴圈來匹配,用這種方式就可以實現乙個字串是否包含另乙個字串了,這種演算法我們稱為 bf演算法。bf演算法,即暴力 brute force 演算法,是普通的模式匹配演算法,bf演算法的思想就是將目標串 s 的第乙個字元與模式串 t 的第乙個字元進行匹配,若相...