日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

字符串匹配算法

發(fā)布時(shí)間:2024/8/1 编程问答 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符串匹配算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

字符串匹配就是在主串A中查找模式串B,例如在主串a(chǎn)bababc中查找模式串a(chǎn)bc是否存在,記主串A的長度為n,模式串B的長度為m,n>=m。

BF算法

BF(Brute Force)算法,又叫暴力匹配算法或者樸素匹配算法,思路很簡單:在主串中取前下標(biāo)為[0,m-1]這m個(gè)字符的子串和模式串逐個(gè)字符逐個(gè)字符比較,如果完全一樣就結(jié)束并返回下標(biāo);如果有不一樣的,那么主串中的子串后移一位,主串中[1,m]這個(gè)子串和模式串繼續(xù)比較,… ,主串中[n-m,n-1]這個(gè)子串和模式串繼續(xù)比較。主串中長度為m的子串有n-m+1個(gè)。


?

int BF(std::string &s,std::string &pattern) {int n = s.length(), m = pattern.length();for (int i = 0; i < n-m+1; i++) {int j = 0;for (; j < m; j++) {if (s[i + j] != pattern[j])break;}if(j==m)return i;?? ?//匹配到了,返回主串中的下標(biāo)}return -1;?? ?//匹配不到 }

最壞的情況下,在第一個(gè)for循環(huán)里,i 從0到n-m走滿共n-m+1次,第二個(gè)for循環(huán)里,j 從0到m-1走滿共m次,因此最壞的情況下時(shí)間復(fù)雜度為O(n*m),舉個(gè)例子,在bbbbbbf中查找bf,所有n-m+1個(gè)子串都要走完,并且每次和模式串比較都要比較m次,總共比較n-m+1次。
BF算法最大的優(yōu)點(diǎn)就是簡單,代碼不容易出錯(cuò),在主串和模式串的長度都不大的時(shí)候還是比較實(shí)用的。

RK算法

RK(Rabin-Karp)算法,是用兩個(gè)發(fā)明者的名字命名的。思路也比較簡單:對主串中n-m+1個(gè)子串求哈希值,模式串也求哈希值,然后比較子串的哈希值和模式串的哈希值,如果不相等證明不匹配,如果相等就匹配(在沒有哈希沖突的情況,沖突的情況后面會講)。
??這個(gè)算法對哈希函數(shù)的設(shè)計(jì)要求會高一點(diǎn),當(dāng)然最好就不存在哈希沖突,就會比較簡單,相等就匹配,不相等就不匹配。
??來看看這樣一個(gè)設(shè)計(jì):假設(shè)主串和模式串只有a-j這10個(gè)字母,我們可以直接將字符串映射成整數(shù)(a-j對應(yīng)十進(jìn)制0-9),例如bcd我們可以直接映射成bcd=1*10*10+2*10+3=123,這樣就不存在哈希沖突了。那如果現(xiàn)在是a-z這26個(gè)字母,我們可以用同樣的思路,但是使用26進(jìn)制,a-z對應(yīng)0-25:例如bcd=1*26*26+2*26+3=731。
??這個(gè)哈希函數(shù)是有規(guī)律的,當(dāng)前子串的哈希值hash[i]是可以根據(jù)上一個(gè)子串的哈希值hash[i-1]計(jì)算得到,來看看下面這個(gè)例子:


上面的子串a(chǎn)ba的起始坐標(biāo)為i-1,哈希值為hash[i-1],下面子串bab的起始坐標(biāo)為i,哈希值為hash[i],我們知道兩個(gè)子串中都有ba,但是下面的ba映射成的值要比上面的ba要大26倍,因?yàn)樗诘奈恢貌灰粯?#xff0c;下面的ba在最高位和第二位,下面的ba在第二位和第三位,那么我們將hash[i-1]乘26,上下子串ba的hash值都相同了,然后再減去上面子串的最高位a(注意此時(shí)的a也是乘多了個(gè)26的),最后加上下面子串的末尾的b即可。最終的計(jì)算結(jié)果就同上圖中的計(jì)算一樣,注意藍(lán)色框框的m即可,是m而不是m-1,因?yàn)閔ash[i-1]乘了26。

//假設(shè)哈希值不會溢出int的范圍? int RK(std::string& s, std::string& pattern) {int n = s.length(), m = pattern.length();int p = pow(26, m);?? ?//26的m次方int* hash = new int[n - m + 1];hash[0] = s[0] - 'a';int hash_pattern = pattern[0] - 'a';for (int i = 1; i < m; i++) {?? ??? ??? ??? ?//求第一個(gè)子串的哈希值hash[0]和模式串的哈希值hash_patternhash[0] = hash[0] * 26 + s[i] - 'a';hash_pattern = hash_pattern * 26 + pattern[i] - 'a';}for (int i = 1; i < n - m + 1; i++)?? ??? ?//根據(jù)前一個(gè)子串的哈希值求所有的子串的哈希值,代入上圖的公式hash[i] = 26 * hash[i - 1] - (s[i - 1] - 'a') * p + (s[i + m - 1] - 'a');for (int i = 0; i < n - m + 1; i++)?? ??? ?//比較模式串的哈希值hash_pattern和每個(gè)子串的哈希值if (hash[i] == hash_pattern)?? ??? ?//相同即匹配return i;return -1;?? ?//不匹配 }int main() {std::string a = "abababc";std::string p = "abc";std::cout << RK(a, p) << std::endl; }

遍歷一次主串就可以求出所有子串的哈希值了,求一個(gè)子串的哈希值時(shí)間復(fù)雜度可以看做O(1),求所有子串的哈希值的時(shí)間復(fù)雜度為O(n)。模式串和子串的哈希值比較時(shí)間復(fù)雜度為O(1),共有n-m+1個(gè)子串即比較n-m+1次,所以時(shí)間復(fù)雜度為O(n)。所以RK算法的時(shí)間復(fù)雜度為O(n)。

如果模式串的長度m太大,字符不止26個(gè)字母,我們上面設(shè)計(jì)的算法可能會溢出整型數(shù)據(jù)的范圍,我們也可以設(shè)計(jì)別的哈希函數(shù):例如每種字符對應(yīng)一個(gè)小質(zhì)數(shù),然后將所有字符對應(yīng)的質(zhì)數(shù)相加得到哈希值,這樣算出來的哈希值會比較小,基本不會溢出,但是可能會造成哈希沖突。
??存在哈希沖突的情況下,我們對比子串的哈希值和模式串的哈希值,如果不相等還是證明兩個(gè)串不匹配;如果相等,由于存在哈希沖突的情況,我們還不能判定子串和模式串相等,還需要逐個(gè)字符進(jìn)行比較,如果每個(gè)字符都相同,才能證明匹配。
??在極端的情況下,存在大量哈希沖突,RK算法會退化BF算法,時(shí)間復(fù)雜度為O(n*m)。

KMP算法

KMP算法是一種改進(jìn)的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,也是由這三位作者的名字進(jìn)行命名的,用i 遍歷主串,j 遍歷模式串,主要的思想就是主串的 i 不回溯,模式串的 j 回溯到某個(gè)位置k,使得模式串的[0,k-1]的位置和主串[i-k,i-1]的位置直接匹配。來看看下面的例子:


??這個(gè)例子中,我們一直比較s[i]和pattern[j]的值,當(dāng)i=j=4的時(shí)候也就是上圖中的紅色框框的時(shí)候,s[i]!=pattern[j],此時(shí)如果按照BF算法,i 回溯到1,j 回溯到0繼續(xù)比對,但其實(shí)是不必要的,因?yàn)閕 回溯到1,s[i]=‘b’,而j 回溯到0,pattern[j]=‘a(chǎn)’,很明顯是不匹配的;來看看KMP算法的做法:主串不回溯也就是 i 不動,j 回溯到 k的位置,使得模式串的[0,k-1]的位置和主串[i-k,i-1]的位置直接匹配(下圖中 j 前的a和 i 前的a匹配,即藍(lán)色框框的部分直接匹配):

那現(xiàn)在問題就變成了位置k的確定。前面說到k的位置要滿足:模式串的[0,k-1]的位置和主串[i-k,i-1]的位置直接匹配,也就是第二幅圖中藍(lán)色框框的部分匹配。那再來看看第一幅圖中的兩個(gè)綠色框框,可以發(fā)現(xiàn)模式串的[j-k,j-1]和主串的[i-k,i-1]部分相等,整理得到:

pattern[0]~pattern[k-1] ?= ?s[i-k]~s[i-1] pattern[j-k]~pattern[j-1] ?= ?s[i-k]~s[i-1]

兩個(gè)等式右邊部分都相等,所以我們可以得到兩個(gè)等式左邊部分相等:

pattern[0]~pattern[k-1] =pattern[j-k]~pattern[j-1]

其實(shí)就是上面這幅圖中3個(gè)綠色的框框,整個(gè)道理也很簡單:就是因?yàn)閕 和 j前的a相等,而j 前的a 和 k前的a 相等,所以我們下次回溯的時(shí)候,就用k 前的a 對準(zhǔn) i 前的a,有機(jī)會可以匹配成功,而省略了BF算法中的多次不必要的回溯和比較。
??我們現(xiàn)在可以知道k的位置是由模式串本身來確定的,和主串無關(guān):pattern[0]~pattern[k-1] =pattern[j-k]~pattern[j-1],也就是說模式串中每一個(gè)字符pattern[j]都對應(yīng)著一個(gè)k值,這個(gè)k值只與模式串有關(guān),我們用next[j]表示pattern[j]對應(yīng)的k值,next數(shù)組的求解就是KMP算法的關(guān)鍵。
??next[j]就是模式串[0,j-1]的子串中真前綴和真后綴的最長可匹配長度,下面舉一個(gè)例子(模式串為ababc):

??j=0時(shí),next[0]=-1表示不存在,因?yàn)楫?dāng)j=0的時(shí)候,j-1=-1是非法下標(biāo)。
??j=1時(shí),[0,j-1]的子串只有一個(gè)a,沒有真前綴和真后綴(因?yàn)檎媲熬Y真后綴不能包含自身),此時(shí)next[1]=0。
??j=2時(shí),[0,j-1]的子串為ab,此時(shí)【真前綴為a,真后綴為b】,可最長匹配長度為0,所以next[2]=0;
??j=3時(shí),[0,j-1]的子串為aba,此時(shí)【真前綴為a,真后綴為a】,還有一種組合【真前綴為ab,真后綴為ba】,第一個(gè)組合的匹配長度為1,第二個(gè)組合的匹配長度為0,最長匹配長度為1,所以next[3]=1。
??j=4時(shí),[0,j-1]的子串為abab,此時(shí)的組合有:【真前綴為a,真后綴為b】,【真前綴為ab,真后綴為ab】,【真前綴為aba,真后綴為bab】,匹配長度分別為0,2,0,最長匹配長度為2,所以next[4]=2。

??上面這種方法只是我們用人腦計(jì)算真前綴和真后綴的最長可匹配長度,那要是讓計(jì)算機(jī)來如何計(jì)算呢?我們貼出代碼,再結(jié)合代碼進(jìn)行解釋:

void getnext(std::string &pattern, int next[]) {?? ?//next的長度為mint m = pattern.length();int k = -1 ,j = 0 ;next[0] = -1;while (j < m) {if (k == -1 || pattern[j] == pattern[k])next[++j] = ++k;elsek = next[k];} }


前三行代碼應(yīng)該沒啥問題,k和j相當(dāng)于兩個(gè)快慢指針,k用來找真前綴,j用來找真后綴。next[j]=k要滿足的關(guān)系也正如我們前面提到的:

pattern[0]~pattern[k-1] =pattern[j-k]~pattern[j-1]

接下來是while循環(huán),j的另一個(gè)作用是用來遍歷模式串的,所以循環(huán)的條件是j<m。
??先讓我們看下if分支,先忽略k==-1這個(gè)判定條件,pattern[j] == pattern[k]的時(shí)候next[++j] = ++k。這個(gè)應(yīng)該比較好理解,其實(shí)就和上面這條等式差不多,上面這條等式是next[j]=k要滿足的要求,而代碼這里是next[j+1]=k+1要滿足的要求。
??再來看看為什么要判斷k==-1,首先k初始化為-1,因?yàn)閖是從0開始的,j是快指針,k是慢指針,所以k要從-1開始。if分支里要訪問pattern[k]的值,k為-1的時(shí)候是非法下標(biāo);其次在else語句中,k = next[k]導(dǎo)致了k是會往前走的(也就是k會變小),有可能k回退到next[0]的時(shí)候又會變?yōu)?1了,所以在訪問pattern[k]的時(shí)候又會是非法下標(biāo)。綜上所述,判斷k==-1是為了保證訪問pattern[k]時(shí)數(shù)組下標(biāo)合法。
??整段代碼的關(guān)鍵就在于else分支的k = next[k](也就是k!=-1且pattern[j] != pattern[k]),也是最難懂的地方,讓我們來看個(gè)例子:

??如圖,現(xiàn)在已知next[13]=6,求next[14],所以兩個(gè)橙色框框內(nèi)長度為6的真前綴和真后綴是相同的(也就是0和7相同,1和8相同,2和9相同以此類推…最后5和12相同);假如現(xiàn)在走if分支:pattern[k]==pattern[j]即pattern[6]==pattern[13]的話,那么執(zhí)行next[++j] = ++k即next[14]=7,這個(gè)應(yīng)該沒啥問題。
??那如果走的else分支呢?pattern[k]!=pattern[j]即pattern[6]!=pattern[13]:k = next[k]


??現(xiàn)在假設(shè)next[k]=i,如圖所示,那么代表(0和1的綠框的兩個(gè)真前綴和4和5的藍(lán)框的后前綴相同),但是前面說過兩個(gè)橙色框相同,可以推出兩個(gè)綠框相同,兩個(gè)籃筐也相同,最終推導(dǎo)出兩個(gè)籃筐和兩個(gè)綠框總共4個(gè)框框里面的字符串都相同(即0、4,、7、11相同;1、5、8、12相同);我們的目的主要是為了證明(0和1的綠框 與 11和12的藍(lán)框相同),那么現(xiàn)在只需比較pattern[j]是否等于pattern[i],如果相等next[++j]=++i也即next[14]=3。而我們?yōu)榱诉壿嫿y(tǒng)一,將 i 賦值給k,即k=next[k],那么又可以回到if的分支和else的分支進(jìn)行判斷了。

?

??如果還不明白為什么k要初始化為1,代碼也可以這樣寫:k初始化為0,j初始化為1,如果pattern[j] == pattern[k]那么next[2]=1這里應(yīng)該沒問題,因?yàn)閗指向真前綴,j指向真后綴。但是仍要判斷k==-1,因?yàn)閚ext[0]=-1,k回退時(shí)有可能還是會出現(xiàn)-1的情況。其次 next[1]=0這里可能會溢出,因?yàn)閙=1的時(shí)候next數(shù)組的長度也只有1。我們可以將next[1]也并入下面的邏輯,也就是k從-1開始,j從0開始,同樣的if else邏輯也可以計(jì)算出next[1]=0,所以我們不采取下面這種寫法,而采用上面的寫法。

void getnext(std::string &pattern, int next[]) {?? ?//next的長度為mint m = pattern.length();int j = 1, k = 0;next[0] = -1;next[1] = 0;?? ?//模式串的長度m可能只有1,所以這里有可能會溢出while (j < m) {if (k == -1 || pattern[j] == pattern[k])?? ?//next[0]=-1,k回退時(shí)有可能還是會出現(xiàn)-1的情況next[++j] = ++k;elsek = next[k];} }

??在構(gòu)建完next數(shù)組后,剩下的部分就簡單了:

int KMP(std::string& s, std::string& pattern) {int n = s.length(), m = pattern.length(), j = 0, i = 0;int* next = new int[m];getnext(pattern, next);while (i < n && j < m) {if (j == -1 || s[i] == pattern[j]) {++i;++j;}elsej = next[j];}if (j == m)?? ?//j走完整個(gè)pattern證明匹配成功,也會退出while循環(huán)return i - m; //返回匹配開始的位置,這里return i-j和return i-m是一樣的,因?yàn)閖==mreturn -1; }


??前面說過,kmp算法主串不回溯,也就是i是不回溯的,一直往上加遍歷主串,如果j==-1或者s[i] == pattern[j]時(shí),i和j分別自加,準(zhǔn)備下一個(gè)字符的比較,否則j回溯到next[j]的位置,回溯后pattern[0]~pattern[j-1] = s[i-j]~s[i-1],也就是說j前面的字符串和主串是已經(jīng)匹配的了,只需要繼續(xù)比較pattern[j]和s[i]。
??while循環(huán)結(jié)束的情況有:i==n或者j==m或者(i==n且j==m),只要j==m就證明匹配成功,因?yàn)閖走完了整個(gè)pattern,說明每個(gè)pattern的字符在主串中都能匹配上。完整代碼:

void getnext(std::string &pattern, int next[]) {?? ?//next的長度為mint m = pattern.length();int j = 0, k = -1;next[0] = -1;while (j < m) {if (k == -1 || pattern[j] == pattern[k])next[++j] = ++k;elsek = next[k];} }int KMP(std::string& s, std::string& pattern) {int n = s.length(), m = pattern.length(), j = 0, i = 0;int* next = new int[m];getnext(pattern, next);while (i < n && j < m) {if (j == -1 || s[i] == pattern[j]) {++i;++j;}elsej = next[j];}if (j == m)?? ?//j走完整個(gè)pattern證明匹配成功,也會退出while循環(huán)return i - m; //返回匹配開始的位置,這里return i-j和return i-m是一樣的,因?yàn)閖==mreturn -1; }int main() {std::string a = "abababc";std::string p = "abc";std::cout << KMP(a, p) << std::endl; }

??KMP算法使用了額外的next數(shù)組,長度是pattern的長度m,所以空間復(fù)雜度是O(m)。
??getnext函數(shù)的時(shí)間復(fù)雜度為O(m),KMP函數(shù)中的while循環(huán)時(shí)間復(fù)雜度為O(n),因此KMP算法的時(shí)間復(fù)雜度為O(m+n)。

BM算法

我們在文本編輯器中,我們經(jīng)常用到查找及替換功能。比如說,在Word文件中,通過查找及替換功能,可以把某一個(gè)單詞統(tǒng)一替換成另一個(gè)單詞。對于文本編輯器這種軟件來說,查找及替換是其核心功能,我們希望使用的字符串匹配算法盡可能地高效。之前討論過RK算法,時(shí)間復(fù)雜度為O(n),其實(shí)已經(jīng)很高效了,現(xiàn)在來介紹一個(gè)新的字符串匹配算法,BM(Boyer-Moore)算法。

模式串和主串的匹配過程可以看成模式串在主串中不停的向后滑動。當(dāng)遇到不匹配的字符時(shí),BF算法和RK算法是將模式串往后滑動一位,然后從模式串的第一個(gè)字符開始重新匹配。

主串中的字符c在模式串中沒有對應(yīng)的字符,就肯定無法匹配。因此,我們可以一次性把模式串往后多滑動幾位,把模式串移動到字符c的后面,如下圖。

其實(shí),BM算法本質(zhì)上就是在尋找某種規(guī)律,借助這種規(guī)律,在模式串與主串匹配的時(shí)候,當(dāng)模式串與主串中的某個(gè)字符不匹配時(shí),能夠跳過一些肯定不會匹配的情況,將模式串往后多滑動幾位。字符串匹配的效率因此就高了。

4.2 BM算法的原理分析

BM算法的具體實(shí)現(xiàn)原理包含兩個(gè)部分:壞字符規(guī)則(bad character rule)和好后綴規(guī)則(good suffix rule)。

1.壞字符規(guī)則
我們知道在BF算法中的模式串和主串之間的匹配是按照下標(biāo)從小到大的順序進(jìn)行的,而BM算法的匹配順序卻是比較特殊,他是按照模式串下標(biāo)從大到小的順序倒敘進(jìn)行的。如下圖。

從模式串的末尾往前倒著匹配,當(dāng)發(fā)現(xiàn)某個(gè)字符無法匹配的時(shí)候,我們就把這個(gè)無法匹配的字符稱為“壞”字符。注意,壞字符指的是主串中的字符,而不是模式串中的字符。如下圖。

我們用壞字符c在模式串中查找,發(fā)現(xiàn)模式串中并不存在這個(gè)字符,也就是說,字符c與模式串中的任何字符都不可能匹配。這個(gè)時(shí)候,我們就可以將模式串直接滑動到字符c的后面,再重新從模式串的末尾字符開始比較。

?

我們將模式串滑動到c之后,就會發(fā)現(xiàn),模式串中的最后一個(gè)字符d,還是無法與主串中的字符a相互匹配。此時(shí),我們是否能將模式串滑動到主串中壞字符a(主串中第三個(gè)a)的后面?

其實(shí)是不可以的,因?yàn)閴淖址鸻在模式串中存在,也就是下標(biāo)為0的位置存儲的就是字符a。因此,我們可以將模式串往后滑動兩位,讓模式串中的a與主串中的第三個(gè)a上下對齊,然后再從模式串的末尾字符開始匹配。

?

?現(xiàn)在大家可能會發(fā)現(xiàn)一個(gè)問題,那就是,第一次我們移動模式串的時(shí)候,是移動了三位,但是第二次的時(shí)候就是移動了兩位,那么對于移動的具體次數(shù),有沒有規(guī)律呢?

當(dāng)模式串與主串不匹配時(shí),我們把壞字符對應(yīng)的模式串中的字符在模式串中的下標(biāo)記作為si。如果壞字符在模式串中存在,那么我們把壞字符在模式串中的下標(biāo)記作xi,如果壞字符在模式串中不存在,那么我們把xi記作-1。那么,模式串往后滑動的位數(shù)就等于si-xi。

?

?這里還要說明的是,如果壞字符在模式串中出現(xiàn)多次,那么在計(jì)算xi的時(shí)候,我們選擇模式串中最靠后的哪個(gè)壞字符的下標(biāo)作為xi的值。這樣就不會因?yàn)槟J礁Z滑動過多,而導(dǎo)致本來可能匹配的情況被忽略。

利用壞字符規(guī)則,BM算法在最好情況下的時(shí)間復(fù)雜度非常底,是O(n/m)。例如,主串是aaabaaabaaabaaab,模式串是aaaa,每當(dāng)模式串與主串不匹配時(shí)(壞字符是b),我們就可以將模式串直接往后滑動4位,因此,匹配具有類似特點(diǎn)的主串與模式串的時(shí)候,BM算法是高效的。

不過,單純使用壞字符規(guī)則還不夠,因?yàn)楦鶕?jù)si-xi計(jì)算出來的滑動位數(shù)又可能是負(fù)數(shù),如主串是aaaaaaaaaaaa,模式串為baaa。針對這種情況,就還需要另外一種規(guī)則,好后綴規(guī)則。

2.好后綴規(guī)則

好后綴規(guī)則與壞字符規(guī)則非常類似,當(dāng)模式串滑動到如下圖所示的位置時(shí),模式串與主串有兩個(gè)字符是匹配的,倒數(shù)第三個(gè)字符不匹配。

?

先來看看好后綴規(guī)則怎么工作的。

我們把已經(jīng)匹配的"bc"稱為好后綴,記作{u}.我們用他在模式串中進(jìn)行查找,如果找到另一個(gè)與好后綴{u}匹配的子串{u*},那么我們就將模式串滑動到子串{u*}與好后綴{u}上下對齊的位置。如下圖。

?

?如果在模式串中找不到好后綴{u}匹配的另外的子串,就直接將模式串滑動到好后綴{u}的后面。

?

?不過大家想沒想過這個(gè)問題,當(dāng)模式串中不存在與好后綴{u}匹配的子串時(shí),我們直接將模式串滑動到好后綴{u}后面,是不是有點(diǎn)過頭,看下圖一個(gè)例子,其中"bc"是好后綴,盡管在模式串中沒有另外一個(gè)與好后綴匹配的子串,但是我們?nèi)绻J酱苿拥胶煤缶Y的后面,就會錯(cuò)過模式串和主串可以匹配的情況。

?

如果好后綴在模式串中不存在可匹配的子串,那在我們一步一步往后滑動模式串的過程中, 只要主串中的{u}與模式串有重合,那肯定就無法完全匹配。但是當(dāng)模式串滑動到前綴與主 串中{u}的后綴有部分重合的時(shí)候,并且重合的部分相等的時(shí)候,就有可能會存在完全匹配 的情況。
?

?

所以,針對這種情況,我們不僅要看好后綴在模式串中,是否有另一個(gè)匹配的子串,我們還
要考察好后綴的后綴子串,是否存在跟模式串的前綴子串匹配的。
所謂某個(gè)字符串 s 的后綴子串,就是最后一個(gè)字符跟 s 對齊的子串,比如 abc 的后綴子串 就包括 c, bc。所謂前綴子串,就是起始字符跟 s 對齊的子串,比如 abc 的前綴子串有 a, ab。我們從好后綴的后綴子串中,找一個(gè)最長的并且能跟模式串的前綴子串匹配的,假設(shè) BM是{v},然后將模式串滑動到如圖所示的位置。

?

當(dāng)模式串和主串中的 某個(gè)字符不匹配的時(shí)候,如何選擇用好后綴規(guī)則還是壞字符規(guī)則,來計(jì)算模式串往后滑動的 位數(shù)?
我們可以分別計(jì)算好后綴和壞字符往后滑動的位數(shù),然后取兩個(gè)數(shù)中最大的,作為模式串往 后滑動的位數(shù)。這種處理方法還可以避免我們前面提到的,根據(jù)壞字符規(guī)則,計(jì)算得到的往 后滑動的位數(shù),有可能是負(fù)數(shù)的情況。

BM算法的代碼實(shí)現(xiàn)


“壞字符規(guī)則”本身不難理解。當(dāng)遇到壞字符時(shí),要計(jì)算往后移動的位數(shù) si-xi,其中 xi 的 計(jì)算是重點(diǎn),我們?nèi)绾吻蟮?xi 呢?或者說,如何查找壞字符在模式串中出現(xiàn)的位置呢?如果我們拿壞符在模式串中順序遍歷查找,這樣就會比較低效,勢必影響這個(gè)算法的性 能。有沒有更加高效的方式呢?我們之前學(xué)的散列表,這里可以派上用場了。我們可以將模 式串中的每個(gè)字符及其下標(biāo)都存到散列表中。這樣就可以快速找到壞字符在模式串的位置下 標(biāo)了。
關(guān)于這個(gè)散列表,我們只實(shí)現(xiàn)一種最簡單的情況,假設(shè)字符串的字符集不是很大,每個(gè)字符 長度是 1 字節(jié),我們用大小為 256 的數(shù)組,來記錄每個(gè)字符在模式串中出現(xiàn)的位置。數(shù)組 的下標(biāo)對應(yīng)字符的 ASCII 碼值,數(shù)組中存儲這個(gè)字符在模式串中出現(xiàn)的位置。

?

哈希表的代碼構(gòu)建過程

private static final int SIZE = 256;//全局變量或成員變量//b為模式串,m為模式串長度,bc為哈希表 pivate void generateBC(char[] b,int m,int[] bc){for(int i = 0;i < SIZE;++i){bc[i] = -1; ? //初始化bc}for(int i = 0;i < m;++i){int ascii = (int)b[i];//計(jì)算b[i]的ASCII值bc[ascii] = i;?}? }


掌握了壞字符規(guī)則之后,我們先把 BM 算法代碼的大框架寫好,先不考慮好后綴規(guī)則,僅
用壞字符規(guī)則,并且不考慮 si-xi 計(jì)算得到的移動位數(shù)可能會出現(xiàn)負(fù)數(shù)的情況。

public int bm(char[] a,int n,char[] b,int m){int[] bc = new int[SIZE];//記錄模式串中每個(gè)字符出現(xiàn)的位置generateBC(b,m,bc);//構(gòu)建壞字符哈希表int i = 0;//i表示主串與模式串上下對齊的第一個(gè)字符while(i < n-m){int j;for(j = m - 1;j >= 0;--j){ ? //模式串從后往前匹配if(a[i+j] != b[j]) break; ? //壞字符對應(yīng)的模式串中的下標(biāo)是j}if(j < 0){return i; ? //匹配成功,返回主串與模式串第一個(gè)匹配的字符的位置}//這里將等同于模式串往后滑動j-bc[(int)a[i+j]]位i = i + (j - bc[(int)a[i+j]]);}return -1; }


?BM算法代碼實(shí)現(xiàn)中的關(guān)鍵變量。

?

大家載堅(jiān)持一下看完好后綴規(guī)則的實(shí)現(xiàn)

我們先簡單回顧一下,前面講過好后綴的處理規(guī)則中最核心的內(nèi)容:
在模式串中,查找跟好后綴匹配的另一個(gè)子串;
在好后綴的后綴子串中,查找最長的、能跟模式串前綴子串匹配的后綴子串;
在不考慮效率的情況下,這兩個(gè)操作都可以用很“暴力”的匹配查找方式解決。但是,如果 想要 BM 算法的效率很高,這部分就不能太低效。如何來做呢?
因?yàn)楹煤缶Y也是模式串本身的后綴子串,所以,我們可以在模式串和主串正式匹配之前,通 過預(yù)處理模式串,預(yù)先計(jì)算好模式串的每個(gè)后綴子串,對應(yīng)的另一個(gè)可匹配子串的位置。這 個(gè)預(yù)處理過程比較有技巧,很不好懂,應(yīng)該是這節(jié)最難懂的內(nèi)容了,你要認(rèn)真多讀幾遍。 我們先來看,如何表示模式串中不同的后綴子串呢? 因?yàn)楹缶Y子串的最后一個(gè)字符的位置是 固定的,下標(biāo)為 m-1,我們只需要記錄長度就可以了。通過長度,我們可以確定一個(gè)唯一 的后綴子串

?

現(xiàn)在,我們要 引入最關(guān)鍵的變量 suffix 數(shù)組 。suffix 數(shù)組的下標(biāo) k,表示后綴子串的長 度,下標(biāo)對應(yīng)的數(shù)組值存儲的是,在模式串中跟好后綴{u}相匹配的子串{u*}的起始下標(biāo)值。這句話不好理解,我舉一個(gè)例子。

?

但是,如果模式串中有多個(gè)(大于 1 個(gè))子串跟后綴子串{u}匹配,那 suffix 數(shù)組中該存儲 哪一個(gè)子串的起始位置呢?為了避免模式串往后滑動得過頭了,我們肯定要存儲模式串中最 靠后的那個(gè)子串的起始位置,也就是下標(biāo)最大的那個(gè)子串的起始位置。不過,這樣處理就足 夠了嗎?
實(shí)際上,僅僅是選最靠后的子串片段來存儲是不夠的。我們再回憶一下好后綴規(guī)則。 我們不僅要在模式串中,查找跟好后綴匹配的另一個(gè)子串,還要在好后綴的后綴子串中,查 找最長的能跟模式串前綴子串匹配的后綴子串。
如果我們只記錄剛剛定義的 suffix,實(shí)際上,只能處理規(guī)則的前半部分,也就是,在模式串 中,查找跟好后綴匹配的另一個(gè)子串。所以,除了 suffix 數(shù)組之外,我們還需要另外一個(gè) boolean 類型的 prefix 數(shù)組,來記錄模式串的后綴子串是否能匹配模式串的前綴子串。
?

?

現(xiàn)在,我們來看下, 如何來計(jì)算并填充這兩個(gè)數(shù)組的值 ?這個(gè)計(jì)算過程非常巧妙。
我們拿下標(biāo)從 0 到 i 的子串(i 可以是 0 到 m-2)與整個(gè)模式串,求公共后綴子串。如果
公共后綴子串的長度是 k,那我們就記錄 suffix[k]=j(j 表示公共后綴子串的起始下標(biāo))。
如果 j 等于 0,也就是說,公共后綴子串也是模式串的前綴子串,我們就記錄
prefix[k]=true。

?

我們把 suffix 數(shù)組和 prefix 數(shù)組的計(jì)算過程,用代碼實(shí)現(xiàn)出來,就是下面這個(gè)樣子:?

void generateGS(char[] b,int m,int[] suffix,boolean[] prefix){for(int i = 0;i < m;++i){//初始化suffix,prefix數(shù)組suffix[i] = -1;prefix[i] = false;}for(int i = 0;i < m - 1;++i){//循環(huán)處理b[0,i]int j = i;intk = 0;//公共后綴子串的長度while(j >= 0 && b[j] == b[m-1-k]){//與b[0,m-1]求公共后綴子串--j;++k;suffix[k] = j+1;//j+1表示公共后綴子串在b[0,i]中的起始下標(biāo)}if(j == -1) prefix[k] = true; ? //公共后綴子串也是模式串的前綴子串} }

有了這兩個(gè)數(shù)組之后,我們現(xiàn)在來看, 在模式串跟主串匹配的過程中,遇到不能匹配的字符
時(shí),如何根據(jù)好后綴規(guī)則,計(jì)算模式串往后滑動的位數(shù)?
假設(shè)好后綴的長度是 k。我們先拿好后綴,在 suffix 數(shù)組中查找其匹配的子串。如果
suffix[k] 不等于 -1(-1 表示不存在匹配的子串),那我們就將模式串往后移動 j-suffix[k]+1 位(j 表示壞字符對應(yīng)的模式串中的字符下標(biāo))。如果 suffix[k] 等于 -1,表示 模式串中不存在另一個(gè)跟好后綴匹配的子串片段。我們可以用下面這條規(guī)則來處理。

?

好后綴的后綴子串 b[r, m-1](其中,r 取值從 j+2 到 m-1)的長度 k=m-r,如果 prefix[k] 等于 true,表示長度為 k 的后綴子串,有可匹配的前綴子串,這樣我們可以把模 式串后移 r 位。

?

如果兩條規(guī)則都沒有找到可以匹配好后綴及其后綴子串的子串,我們就將整個(gè)模式串后移
m 位。

?

至此,好后綴規(guī)則的代碼實(shí)現(xiàn)我們也講完了。我們把好后綴規(guī)則加到前面的代碼框架里,就
可以得到 BM 算法的完整版代碼實(shí)現(xiàn)。

//a和b分別表示主串和模式串,n和m分別表示主串和模式串的長度 public int bm(char[] a,int n,char[] b,int m){int[] bc = new int[SIZE];//記錄模式串中每個(gè)字符最后出現(xiàn)的位置generateBC(b,m,bc);//構(gòu)建壞字符哈希表int[] suffix = new int[m];boolean[] prefix = new boolean[m];generateGS(b,m,suffix,prefix);int i = 0;//表示主串與模式串匹配的第一個(gè)字符while(i <= n - m){int j;for(j = m - 1;j >= 0;--j){//模式串從后往前匹配if(a[i+j] != b[j]) break; //壞字符對應(yīng)模式串中的下標(biāo)是j}if(j < 0){return i; ? //匹配成功,返回主串與模式串第一個(gè)匹配的字符的位置}int x = j - bc[(int)a[i+j]];int y = 0;if(j < m-1){y = moveByGS(j,m,suffix,prefix);}i = i + Math.max(x,y);}return -1; }//j表示壞字符對應(yīng)的模式串中的字符下標(biāo),m表示模式串長度 private int moveByGs(int j,int m,int[] suffix,boolean[] prefix){int k = m - 1 - j;//好后綴的長度if(suffix[k] != -1) return j - suffix[k] + 1;for(int r = j+2;r <= m-1;++r){if(prefix[m-r] == true){return r;}}return m; }


BM 算法的性能分析及優(yōu)化
我們先來分析 BM 算法的內(nèi)存消耗。
整個(gè)算法用到了額外的 3 個(gè)數(shù)組,其中 bc 數(shù)組的大 小跟字符集大小有關(guān),suffix 數(shù)組和 prefix 數(shù)組的大小跟模式串長度 m 有關(guān)。 如果我們處理字符集很大的字符串匹配問題,bc 數(shù)組對內(nèi)存的消耗就會比較多。因?yàn)楹煤?綴和壞字符規(guī)則是獨(dú)立的,如果我們運(yùn)行的環(huán)境對內(nèi)存要求苛刻,可以只使用好后綴規(guī)則,不使用壞字符規(guī)則,這樣就可以避免 bc 數(shù)組過多的內(nèi)存消耗。不過,單純使用好后綴規(guī)則 的 BM 算法效率就會下降一些了。
對于執(zhí)行效率來說,我們可以先從時(shí)間復(fù)雜度的角度來分析。
基于我目前討論的這個(gè)BM算法,在極端情況下,預(yù)處理計(jì)算 suffix 數(shù)組、prefix 數(shù)組 的性能會比較差。
比如模式串是 aaaaaaa 這種包含很多重復(fù)的字符的模式串,預(yù)處理的時(shí)間復(fù)雜度就是 O(m^2)。當(dāng)然,大部分情況下,時(shí)間復(fù)雜度不會這么差。

總結(jié)

以上是生活随笔為你收集整理的字符串匹配算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

av在线电影网站 | 99欧美精品| 美女视频黄是免费的 | 日韩区欠美精品av视频 | 欧美日韩高清一区二区 国产亚洲免费看 | 国产视频资源 | 狠狠狠色丁香综合久久天下网 | 丝袜美女在线观看 | 免费日韩视频 | 久久久综合九色合综国产精品 | 九九涩涩av台湾日本热热 | 久久久久久福利 | 91麻豆看国产在线紧急地址 | 久久久久免费精品国产 | 色视频网站在线观看一=区 a视频免费在线观看 | 天天插天天干天天操 | 人人添人人 | 久草在线免费看视频 | a天堂一码二码专区 | 成人精品亚洲 | 日本一区二区三区视频在线播放 | 日韩精品一区电影 | 久久九九国产精品 | 国产999久久久 | 在线观看视频一区二区三区 | 日韩精品视频在线观看网址 | 日韩精品免费在线视频 | 国产精品久久久久av免费 | 久久开心激情 | 国产精品久久久久aaaa九色 | 免费午夜网站 | 午夜私人影院 | 久久爱资源网 | 免费在线观看日韩欧美 | 欧美日韩在线第一页 | 国产精品情侣视频 | 日韩视频中文 | 黄色成年片| www178ccom视频在线 | 日批视频在线 | 色婷婷综合在线 | 日批网站免费观看 | 天天爱天天操天天射 | 日韩欧美国产免费播放 | 91在线播放国产 | 国产精品久久免费看 | 亚洲精品人人 | 亚洲黄在线观看 | 日韩精品免费一区二区三区 | 久久视频这里有久久精品视频11 | av最新资源 | 成人禁用看黄a在线 | 中文字幕123区 | 国产精品久久久久久欧美 | 国产精品九九九 | 日韩高清激情 | 69国产成人综合久久精品欧美 | 黄色综合| 天天操夜夜想 | 最新日本中文字幕 | 日韩精品一区二区三区视频播放 | 色天堂在线视频 | 五月天激情电影 | 人人狠狠综合久久亚洲婷 | 国产日韩欧美视频 | 超碰97中文 | 最新国产福利 | 伊人首页| 美女网色 | 免费在线观看av的网站 | 色av男人的天堂免费在线 | 国产中年夫妇高潮精品视频 | 五月婷婷深开心 | 69av在线视频 | 成人在线电影观看 | 国产麻豆果冻传媒在线观看 | 国产精品自产拍在线观看网站 | 日b视频国产 | 色欧美成人精品a∨在线观看 | 天天干亚洲| 久久九九免费视频 | 久久96国产精品久久99软件 | 国产色婷婷精品综合在线手机播放 | 人人澡人人爱 | 精品久久久国产 | 玖玖999 | 国产精品中文在线 | 中文资源在线官网 | 操操操干干干 | 色网址99 | 久久人人爽人人片av | 中文字幕日本在线观看 | 久久精品一区八戒影视 | 一区二区视频电影在线观看 | 国产精品mv | 成人av免费网站 | 五月天综合 | 久久亚洲欧美 | 免费黄色在线播放 | 99精品国产一区二区三区麻豆 | 国产麻豆精品95视频 | 一区久久久 | 天天操天天爱天天干 | 成人影视免费 | 国产91综合一区在线观看 | 国产精品成人免费 | 亚洲成人蜜桃 | 夜色成人网 | 欧美精品久久久久久 | 欧美成a人片在线观看久 | 久久久久久久av | www·22com天天操 | 91av在线播放视频 | 精品嫩模福利一区二区蜜臀 | 亚洲一区 av | 成人在线观看你懂的 | 天堂av中文字幕 | 五月天婷亚洲天综合网精品偷 | 国产精品国内免费一区二区三区 | 成人免费在线视频 | 五月天色站 | 久久av中文字幕片 | 久草在线费播放视频 | 日韩在线观看精品 | 玖玖玖影院 | 成人av影视在线 | 欧美日韩在线第一页 | 激情欧美丁香 | 久久精品亚洲精品国产欧美 | 97超碰影视| 青青草国产成人99久久 | 久久好看 | 亚洲人成综合 | 少妇性色午夜淫片aaaze | 超碰成人网 | 亚州中文av | 国产中文在线字幕 | 国产精品久久久久久久av大片 | 波多野结衣最新 | 蜜臀久久99静品久久久久久 | 精品中文字幕在线观看 | 97超碰影视 | 久久高清片| 久久精品99国产精品酒店日本 | 97超碰中文字幕 | 国产在线国偷精品产拍免费yy | 久久午夜精品视频 | 精品视频99 | 精品一二三区视频 | 免费看污网站 | 天天色天天干天天 | 天天爽天天碰狠狠添 | 91在线精品播放 | 久草在在线视频 | 五月天婷婷丁香花 | 91精品久久久久久久久久久久久 | 久久综合五月天婷婷伊人 | 日韩欧美视频在线播放 | 国产资源在线视频 | 国产精品毛片一区二区在线 | 99这里只有久久精品视频 | 欧美91在线 | 最新av中文字幕 | 97色在线观看 | 久草网在线观看 | 午夜91在线 | 久青草视频 | 亚洲天堂网在线视频 | 久久在线观看 | 天天射天天干天天插 | 91麻豆免费视频 | 成人在线免费看 | 国产综合香蕉五月婷在线 | 久草在线播放视频 | 久久精品网址 | 亚洲女欲精品久久久久久久18 | 亚洲精品合集 | 国产在线黄色 | 国产h片在线观看 | 成人在线视频在线观看 | 国产高清无线码2021 | 久久福利电影 | 欧美日韩在线网站 | 日本精品一区二区三区在线观看 | 国产精品成人在线观看 | 国产精品热 | 国产精品久久99综合免费观看尤物 | 成人影音av | 久久久国产精品久久久 | 性色视频在线 | 日韩大片在线播放 | 色综合天天色 | 国产精品成人一区二区三区吃奶 | 综合精品在线 | 日韩超碰在线 | 色婷婷综合久久久久中文字幕1 | 亚洲精选视频免费看 | 丁香婷婷激情网 | 狠狠网亚洲精品 | 亚洲欧洲一级 | 日本三级久久 | 亚洲一级黄色 | 国产青春久久久国产毛片 | 欧美在线观看视频一区二区 | 天天干天天草天天爽 | 91免费网站在线观看 | 久久嗨| 天天干天天干天天干 | 国产尤物一区二区三区 | 69亚洲视频| 在线观看蜜桃视频 | 国产精品久久久久久模特 | 人人盈棋牌| 成人在线观看免费 | 丰满少妇在线观看网站 | 99热都是精品 | 超碰电影在线观看 | 在线观看国产日韩 | 激情影音先锋 | 免费情趣视频 | 国产精品免费一区二区三区 | 亚洲在线视频免费 | 亚洲午夜大片 | 国产精品手机在线播放 | 亚洲国产精品成人综合 | 亚洲激情视频在线 | 97精品在线视频 | h动漫中文字幕 | 超碰最新网址 | 婷婷伊人网 | 99在线观看视频 | 日日插日日干 | 色婷婷视频网 | 久久九九影视网 | 久久香蕉国产精品麻豆粉嫩av | 欧美一区二区在线 | 美女视频久久黄 | 国产视频在线观看一区二区 | 97超碰资源 | 911国产在线观看 | 国产精品久久久久久久久久99 | 欧洲激情综合 | 国产精品第十页 | 狠狠操欧美| 欧美一级大片在线观看 | av在观看 | 成 人 黄 色 视频免费播放 | 国产精品av免费观看 | 精品在线小视频 | 亚洲综合精品在线 | 免费在线黄色av | 国产在线91精品 | 精品主播网红福利资源观看 | 成人三级黄色 | 国产一区私人高清影院 | 婷婷丁香色 | 在线看的av网站 | 青青河边草手机免费 | 国产成人高清 | 天天干天天摸天天操 | 免费观看的av | 精品国产一区二区三区四区vr | 色播六月天 | 日本爱爱免费视频 | 粉嫩av一区二区三区入口 | 中文字幕视频 | 国产 视频 高清 免费 | .国产精品成人自产拍在线观看6 | 97在线视频免费观看 | 成人av直播 | 片黄色毛片黄色毛片 | 精品99999| 亚洲黄色小说网址 | 国产成人精品一区二区三区网站观看 | 日韩网站免费观看 | 免费男女羞羞的视频网站中文字幕 | 久久国产精品久久精品 | 色噜噜日韩精品欧美一区二区 | 夜夜夜影院 | 久久久96 | 美女av电影 | 操碰av| 亚洲国产中文在线观看 | 久久综合毛片 | 国产日产欧美在线观看 | 日韩电影一区二区三区 | 久草在线资源网 | 国产专区精品视频 | 日韩,中文字幕 | 天天草天天干 | 99久久婷婷国产综合亚洲 | 国产乱视频 | 综合久久影院 | 久久网站免费 | 99久久久久久 | 国产中文字幕网 | 男女啪啪网站 | 97国产精品一区二区 | 精品极品在线 | 成人网看片| 97av色| 97操操| 久保带人 | 国产高清亚洲 | 91精品久久久久久久99蜜桃 | 天天操天天操天天操天天操天天操天天操 | 欧美成年人在线视频 | 国产精品久久久久久一二三四五 | 日韩av进入| 亚洲91精品在线观看 | 美女视频久久久 | 黄色av网站在线免费观看 | 国产精品porn | 久久精品在线免费观看 | 欧美在线视频免费 | 国产精品久久久久久久久久免费 | 91av电影网| 日韩av免费一区二区 | 国产精品福利在线播放 | 波多野结衣视频一区 | 中文字幕一区二区三区精华液 | 日韩色在线| 亚洲最新av网站 | 欧美日韩中文另类 | 黄网站污 | 五月婷在线 | 色姑娘综合网 | 亚洲欧洲精品一区二区精品久久久 | 久久久精品久久日韩一区综合 | 在线播放一区二区三区 | 青青草国产成人99久久 | 亚洲少妇xxxx | 中文字幕黄色网址 | 亚洲乱码国产乱码精品天美传媒 | 亚洲日本va午夜在线影院 | www.国产毛片 | 二区在线播放 | 91丨九色丨蝌蚪丰满 | 天天操天天插 | 日韩午夜电影网 | 亚洲精品一区二区三区在线观看 | 在线免费观看一区二区三区 | 特级aaa毛片 | 欧美国产精品一区二区 | 在线涩涩 | 91精品国产自产在线观看永久 | 麻豆小视频在线观看 | 免费在线观看成年人视频 | 成人99免费视频 | 欧美韩国在线 | av一级在线 | 97**国产露脸精品国产 | 99视频在线精品免费观看2 | 亚洲va欧美va| 97品白浆高清久久久久久 | 国产美女视频 | 激情 婷婷 | 国产91精品在线播放 | 欧美一级片在线 | 91黄色视屏 | 欧美日韩性生活 | 在线观看免费中文字幕 | 中文字幕资源网在线观看 | 久久久精品国产一区二区三区 | 国产亚洲一区二区三区 | 国产亚洲视频在线 | 婷婷中文在线 | 天堂av最新网址 | 日韩精品在线免费播放 | 最近中文国产在线视频 | 亚一亚二国产专区 | 亚洲专区免费观看 | 一级性av| 久草在线99 | 99综合久久 | 国产精品va最新国产精品视频 | 69绿帽绿奴3pvideos | 国产精品视频久久 | 国产又黄又硬又爽 | 国内精品在线看 | www.夜夜骑.com| 最近中文字幕高清字幕免费mv | 色婷婷久久 | 久久久久成人精品亚洲国产 | 91精品在线免费观看 | 六月激情久久 | 97视频网址 | 精品福利国产 | 四虎在线免费视频 | 中文 一区二区 | 国产福利久久 | 伊人天天干 | 亚洲欧美日韩国产一区二区 | 国产在线视频不卡 | 国产午夜三级一二三区 | 日韩在线视频看看 | 99热在线看 | 中文欧美字幕免费 | 国产视频2区 | 69成人在线 | 久久久久在线视频 | 岛国精品一区二区 | 亚洲国产电影在线观看 | 亚洲午夜精品久久久久久久久 | 成人精品视频久久久久 | 国产精品欧美一区二区三区不卡 | 香蕉在线视频观看 | www最近高清中文国语在线观看 | 国产美女久久 | 在线99热| 91福利国产在线观看 | 日韩一级成人av | 久久人操 | a在线免费观看视频 | 99视频国产精品 | 99久久精品网 | 在线免费黄网站 | 91在线超碰 | 国产999精品久久久影片官网 | av大片免费 | 国产精品va最新国产精品视频 | 国产三级国产精品国产专区50 | 欧美午夜精品久久久久 | 国产精品一二 | 美女久久久久久久 | 久久免费的视频 | 亚洲国产一区二区精品专区 | 97超碰人人干 | 国产精品美女久久久久久久网站 | 国产.精品.日韩.另类.中文.在线.播放 | 久操免费视频 | 久久久久久久网 | 91久草视频 | 亚洲h视频在线 | 亚洲国产精品传媒在线观看 | 亚洲欧美视频在线播放 | 国产精品一区二区麻豆 | 国产三级国产精品国产专区50 | 亚洲在线黄色 | 亚洲精品高清一区二区三区四区 | 天堂中文在线视频 | www.xxx.性狂虐 | 日韩色一区二区三区 | 亚洲精品国产品国语在线 | 国产在线视频一区 | 国产玖玖精品视频 | 99精品国产兔费观看久久99 | 激情五月婷婷综合网 | 91看片一区二区三区 | 五月婷婷毛片 | 在线色视频小说 | 久久精品精品电影网 | 免费黄色小网站 | 国产网站在线免费观看 | 99r在线| 国产特级毛片aaaaaa | 骄小bbw搡bbbb揉bbbb | 婷婷丁香激情 | 免费看搞黄视频网站 | 91丨九色丨蝌蚪丨老版 | 91免费的视频在线播放 | 激情网在线观看 | 草久热| 亚洲欧洲在线视频 | 久久久99精品免费观看 | 国产福利免费看 | 精品不卡视频 | 日本在线观看中文字幕无线观看 | 欧美日韩国产色综合一二三四 | 国产午夜一级毛片 | 国产二区视频在线观看 | 麻豆免费视频观看 | 成人影视免费 | 摸bbb搡bbb搡bbbb | 男女激情片在线观看 | 久热香蕉视频 | 91av视频免费在线观看 | 日日操天天操狠狠操 | 美女视频黄是免费的 | 懂色av一区二区三区蜜臀 | 91九色蝌蚪视频 | 免费高清在线视频一区· | 91探花系列在线播放 | 69av网| 91最新在线视频 | 日韩一二三区不卡 | 欧美一级片在线观看视频 | 国产精品毛片网 | 一区二区欧美激情 | 日日夜夜免费精品视频 | 国产在线观看h | 91免费观看视频在线 | 成年人黄色免费网站 | 亚洲最新精品 | 久草在线在线视频 | 九月婷婷人人澡人人添人人爽 | 国产色小视频 | 国产精品久久久久久久毛片 | 国产 日韩 欧美 自拍 | 日韩电影在线观看中文字幕 | 美女国产 | 国产精彩视频一区二区 | 丁香导航| 不卡的av | 在线电影av | 欧美日韩视频网站 | 成人毛片在线观看 | av中文字幕日韩 | 视色网站 | 尤物九九久久国产精品的分类 | www.777奇米| 91手机电影| a级国产乱理论片在线观看 伊人宗合网 | 色爽网站 | 天天操夜夜操 | 亚洲欧洲精品一区二区 | 夜夜高潮夜夜爽国产伦精品 | 日韩免费电影 | 亚洲一区二区三区四区精品 | 一级黄色免费网站 | 伊人永久在线 | 久久五月婷婷丁香 | 亚洲干 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 成人一区二区三区在线 | 天天插天天色 | 正在播放亚洲精品 | 国产麻豆精品久久一二三 | 国产成人黄色在线 | 国产一区二区在线视频观看 | 久久久久久久久久影视 | 五月婷婷.com | 99999精品视频| 国产精品欧美精品 | 国产在线va | 手机av在线不卡 | 日韩av在线高清 | 91精品国自产拍天天拍 | 在线观看一区二区视频 | 成人va视频 | 99精品区 | 亚洲三级在线免费观看 | 久久99国产一区二区三区 | 九九九在线| 日本精品久久久一区二区三区 | 制服丝袜亚洲 | 日韩高清免费在线 | 免费在线观看a v | av不卡中文字幕 | 91一区在线观看 | 亚洲欧洲成人精品av97 | 激情视频在线观看网址 | 欧美精彩视频在线观看 | 国产电影一区二区三区四区 | 国产一区在线播放 | 精品国产网址 | 成全在线视频免费观看 | 91最新视频 | 在线观看免费国产小视频 | 欧美精品亚洲精品 | 中文字幕在线观看视频免费 | av免费网页 | 欧美精品久久久久久久久久丰满 | 久久免费公开视频 | 99综合久久 | 黄色免费网站大全 | 国产一级免费在线 | 国产在线91精品 | 久久特级毛片 | 91精品亚洲影视在线观看 | 日韩精品一区二区三区水蜜桃 | 91热视频 | 免费特级黄色片 | 日韩高清激情 | 日韩在线高清免费视频 | 日韩视频在线观看视频 | 特级毛片爽www免费版 | 欧美一级淫片videoshd | 99久久99久国产黄毛片 | 热热热热热色 | 热久久视久久精品18亚洲精品 | 天天做日日爱夜夜爽 | 激情婷婷六月 | 国产成人精品免高潮在线观看 | 免费激情在线电影 | 美女黄濒| 91av超碰| 日韩中文久久 | 亚洲在线视频免费观看 | 夜夜摸夜夜爽 | 中文字幕一区二区三区乱码在线 | 国产精品24小时在线观看 | 91看片在线 | 黄色一级免费电影 | 国产手机免费视频 | 日韩a在线看 | 欧美在线视频精品 | 午夜久久影视 | 天堂素人在线 | 欧美精品一区二区在线播放 | 色开心| 在线观看91精品视频 | 欧美精品一级视频 | 成人97人人超碰人人99 | 国产精品久久久久aaaa | 91视频链接 | 国产精品久久久免费 | 欧美日韩在线视频观看 | 天天操网站 | 99久久精品国产观看 | 公开超碰在线 | 亚洲黄色免费网站 | 国产91av视频在线观看 | 日韩有色| 91麻豆精品国产自产 | 亚洲欧美国产精品va在线观看 | 国产色在线观看 | 97超碰人| 日韩91av| 青青久草在线视频 | 麻豆一区在线观看 | 日韩视频免费观看高清 | 国产三级精品三级在线观看 | 天天亚洲| 欧美日韩国产精品一区二区三区 | 在线免费av网 | 福利av影院| 色视频网站在线 | 免费观看性生活大片3 | 最近日本mv字幕免费观看 | 亚洲日本在线视频观看 | 99在线观看视频 | 免费观看日韩 | 久草综合在线观看 | 午夜av色 | 96久久久 | 国产精品黄色在线观看 | 成人av直播| 国产一区二区视频在线播放 | 国产精品一区二区在线观看 | 国产精品国内免费一区二区三区 | 999久久久久久久久 69av视频在线观看 | 黄a在线看 | 成人黄色电影在线观看 | 欧美色图狠狠干 | 天天搞天天干天天色 | 国产a级精品 | 国产中文字幕亚洲 | 亚洲人成网站精品片在线观看 | 亚洲精品永久免费视频 | 探花视频在线观看免费 | 精品国产乱码久久久久久1区2匹 | 国产精品久久久久久69 | 亚洲日本va午夜在线影院 | 日日夜夜人人精品 | 免费看搞黄视频网站 | 欧美夫妻生活视频 | 天天射日 | 贫乳av女优大全 | 免费看黄色毛片 | 不卡的av在线播放 | 黄色一级大片在线观看 | 免费色视频网址 | 久久久久久久久久久久av | 亚洲综合成人婷婷小说 | 国产一级精品视频 | 在线观看亚洲精品视频 | www.com久久久 | 黄色一集片 | 亚洲日本中文字幕在线观看 | 日韩午夜精品福利 | 色多多污污在线观看 | 亚洲激情p| 色先锋av资源中文字幕 | 91精品国产欧美一区二区成人 | 99麻豆久久久国产精品免费 | 国产一级片一区二区三区 | 韩国av免费观看 | 麻豆影音先锋 | 久久福利剧场 | 手机在线中文字幕 | 久久久免费 | 91精品视频在线免费观看 | 亚洲成人精品在线观看 | 午夜久久成人 | 日韩欧美综合 | 久久久高清一区二区三区 | 国产免费又爽又刺激在线观看 | 国产精品乱看 | 免费在线国产黄色 | 夜添久久精品亚洲国产精品 | 精品国自产在线观看 | 成人影视免费看 | 视频成人永久免费视频 | 91福利视频在线 | 国产精品久久视频 | 在线观看视频免费播放 | 91高清不卡 | 不卡的av在线 | 日产乱码一二三区别免费 | 粉嫩av一区二区三区四区五区 | 久久久久久久免费观看 | 福利电影一区二区 | 九九涩涩av台湾日本热热 | www视频免费在线观看 | 国产精品资源网 | 亚洲欧美一区二区三区孕妇写真 | 99九九热只有国产精品 | 国产精品欧美激情在线观看 | 色就是色综合 | 国产在线观看污片 | 亚洲最大激情中文字幕 | 一区二区中文字幕在线观看 | 国产精品久久久久久久久久新婚 | 日本最大色倩网站www | 精品国模一区二区三区 | 五月婷香 | 在线中文字幕一区二区 | 国产高清免费在线观看 | 天天干天天上 | 99se视频在线观看 | 黄污污网站 | 激情深爱五月 | 成人久久毛片 | 国内精品99| 天天干天天怕 | 国产手机视频在线播放 | 国产精品毛片久久久久久久 | 在线亚洲高清视频 | 久久久一本精品99久久精品66 | www黄在线 | 欧美一区二区在线看 | 国产黄色片久久 | 综合久久婷婷 | 国产精品久久久久永久免费看 | 最新色站 | 91在线九色 | 日韩高清免费无专码区 | 婷婷丁香六月 | 久久黄色网址 | 国产一区欧美在线 | 99精品电影 | 最近中文字幕mv免费高清在线 | 有码一区二区三区 | 中文字幕中文 | 最新av在线网站 | 欧美一区二区在线免费观看 | 亚洲一级国产 | 成年人在线免费看视频 | 国内精品国产三级国产aⅴ久 | 成人av在线一区二区 | 国产中年夫妇高潮精品视频 | 亚洲日本在线视频观看 | 日韩免费中文 | 欧美日韩视频在线观看免费 | 国产精品一区二区免费看 | 亚洲精品乱码白浆高清久久久久久 | 9797在线看片亚洲精品 | 一区二区三区免费播放 | 久久人人爽人人爽人人片av软件 | 免费视频你懂的 | 国产中文字幕视频在线 | 贫乳av女优大全 | va视频在线 | 在线免费亚洲 | 久久精品三级 | 精品一区二区在线免费观看 | 国产美女精品久久久 | 黄色aa久久 | 亚欧洲精品视频在线观看 | 日本在线观看黄色 | 亚洲成人影音 | 亚洲综合欧美精品电影 | 亚洲精品永久免费视频 | 亚洲精品视频免费在线观看 | 人人草人人草 | 五月激情六月丁香 | 成人黄色国产 | 中文字幕一区二区三区乱码不卡 | 国产日本亚洲高清 | 久久精品这里热有精品 | 国产视频18 | 操久久网 | 久久午夜免费观看 | 黄色小说免费在线观看 | 人人澡人人草 | 亚洲综合激情网 | 黄色av电影 | 日本天天操 | 国产一级二级av | 国产一区成人 | 免费观看一级视频 | 国产午夜精品在线 | 高潮久久久久久 | 在线中文字幕观看 | 精品久久免费看 | 久操免费视频 | 日韩欧美在线不卡 | 色午夜影院 | 天天射天天爱天天干 | 天天综合精品 | 国产色小视频 | 91亚洲欧美激情 | 99超碰在线观看 | 狂野欧美激情性xxxx欧美 | 日韩系列在线 | av品善网| 中文字幕在线影院 | 国产亚洲视频在线 | 国产精品久久久久久久久免费看 | 免费看国产黄色 | 亚洲国产成人精品电影在线观看 | 日日操夜 | 92av视频| www日日 | 西西444www大胆高清图片 | 色综合小说 | 国产又粗又猛又黄 | 日韩最新av在线 | 一级欧美一级日韩 | 欧美激情h| 亚洲撸撸 | 免费精品视频在线观看 | 九九热1 | bbbb操bbbb| 黄色免费高清视频 | 免费三级黄 | 日韩黄色网络 | 久久亚洲专区 | 国产成人一区二区三区在线观看 | 免费观看第二部31集 | 蜜桃av人人夜夜澡人人爽 | 国产原创在线 | 国产一区二区高清视频 | 国产99久久久精品视频 | 婷婷夜夜 | 不卡av免费在线观看 | 欧美在线日韩在线 | 欧美日本不卡视频 | 超碰在线观看av | 91在线网址 | 97视频在线播放 | 99久久精品国产网站 | 黄色精品久久 | 伊人久久电影网 | av成人在线观看 | 91日韩在线专区 | av在线影片 | 综合网色| 日韩有码中文字幕在线 | 久草在线高清视频 | 四季av综合网站 | 在线观看mv的中文字幕网站 | 亚洲第一成网站 | 免费观看十分钟 | 99r在线精品 | 六月色婷 | 国产精品99久久99久久久二8 | 永久免费精品视频网站 | 欧美日韩一区二区三区不卡 | 激情五月色播五月 | 亚洲免费在线播放视频 | 四虎成人免费影院 | 超碰国产人人 | 在线精品观看国产 | 久久九九国产视频 | 懂色av懂色av粉嫩av分享吧 | 日本久久精品视频 | 91精品麻豆 | 免费日韩三级 | 国产视频在 | 91免费网站在线观看 | 久久国产手机看片 | 精品9999| 亚洲精品在线观看的 | 成人黄色电影在线 | 开心激情综合网 | 免费av在线播放 | 天天射天天干天天 | 国产在线观看一 | 精品久久久久久国产91 | 国内免费久久久久久久久久久 | 国产精品久久在线观看 | 欧美日韩国产一区二区在线观看 | 亚洲人人射 | av韩国在线| 日日添夜夜添 | 高清免费av在线 | 国产日韩欧美在线 | 91在线你懂的 | 人人超碰人人 | 91视频在线自拍 | 91看片网址 | 外国av网| 免费色视频网站 | www视频免费在线观看 | 亚洲九九 | 精品自拍网 | 高清av网 | 欧美性天天 | www黄色av | 美国av片在线观看 | 日韩精品中文字幕在线观看 | 成人国产精品久久久 | 天天干天天在线 | 中文字幕在线成人 | 日操干 | 午夜电影中文字幕 | 永久免费精品视频 | 久久黄色成人 | 久久综合色一综合色88 | 久久国产区 | 日韩激情中文字幕 | 欧美国产精品一区二区 | 插插插色综合 | 午夜av剧场| 一区二区视频免费在线观看 | 综合网天天 | 久久精品国产亚洲精品2020 | 亚洲 欧美 综合 在线 精品 | 婷婷色综| 超碰在线cao| 国产亚洲精品精品精品 | 天天操福利视频 | 午夜久久久久久久久久影院 | 国产a国产| 四虎成人免费影院 | 久久99国产精品视频 | 激情综合五月天 | 91精品国产综合久久福利 | 亚洲国产av精品毛片鲁大师 | 91手机视频 | 玖玖在线播放 | 久久国产精品一国产精品 | 久久久在线观看 | 国产精品情侣视频 | 久草在线观看 | 国产五月婷 | 色午夜影院 | 国产黄色精品在线 | 精品国产91亚洲一区二区三区www | 亚洲国产精品va在线看黑人动漫 | 国产亚洲精品美女久久 | 黄色av播放 | 高清av免费一区中文字幕 | 日日夜夜精品免费 | 欧美日韩一区二区免费在线观看 | 天堂在线一区二区三区 | 在线精品视频免费观看 | 99国产精品免费网站 | 久久99国产综合精品免费 | 国外成人在线视频网站 | 在线一二三区 | 天天干天天操天天拍 | 免费福利在线视频 | 九九欧美 | 久久亚洲欧美 | 99精品欧美一区二区三区黑人哦 | 亚洲黄色免费在线看 | 91麻豆精品国产91久久久久久 | 五月婷婷中文字幕 | 色综合久久88色综合天天免费 | 成人免费看片网址 | 超碰在线最新 | 日韩激情免费视频 | 中文字幕在线国产 | 国产成人av电影在线观看 | 国产999在线观看 | 97免费在线观看视频 | 亚洲欧洲日韩 | 亚洲精品小视频 | 粉嫩av一区二区三区四区五区 | 日本中文字幕在线观看 | 五月婷婷中文网 | 激情综合电影网 | 久草精品视频在线播放 | 正在播放国产精品 | 二区三区视频 | 亚洲精品99 | 日韩精品在线免费观看 | 福利片免费看 | 天天色天天干天天色 | 国产一区二区精 | 久久无码精品一区二区三区 | 欧美综合久久 | 成人在线播放av | 天天干 天天摸 天天操 | 国产黄色片久久久 | av超碰在线 | 九九亚洲精品 | 91在线你懂的 | 337p西西人体大胆瓣开下部 | 久久视了| 精品人妖videos欧美人妖 | 六月丁香在线观看 | 97精品国产| 免费情缘| av中文在线观看 |