青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

鍵盤的詠嘆調

常用鏈接

統計

最新評論

KMP算法

   傳統的字符串匹配算法中,為了在一段字符串中查找模式字符串的話需要使用2個循環嵌套起來,例如:
int i=0;
while(i< str.length()-parten.length())
{
    
int j=0;
    
while(parten[j]==str[i])
    
{
        
++i;
        
++j;
    }

    
if(j==parten.length())
        
return true;
    i
=i-j+1;
}

return false;

   

這種方法很黃很暴力,其中對于第一個循環,會產生回溯。也就是說如果一個字符串:

bacbababaabcba來匹配模式字符串abababa。當原字符串的a和模式字符串的c做比較的時候,

b

a

c

b

a

b

a

b

a

a

(i=9)

b

c

b

a

a

b

a

b

a


(j=5)

a

當發現不匹配的時候i會往前遞進一位,此時從原字符串的第i+1位開始匹配字符串:

b

a

c

b

a

b

(i=5)

a

b

a

a

b

c

b

a


(j=0)

b

a

b

a

b

a

Kmp算法就是為了讓i不再回溯而提出的一種算法。在kmp算法中

 

當匹配失敗后,i維持原來的值不變,只需要變動j值即可。我們可以把j值直接加上一個位移忽略掉那些肯定會匹配失敗

的可能,現在的問題是如何求這個位移?

以模式字符串“abababa”為例子,位于字符串第3個位置的字母‘b’和要匹配的字符串T[0..k]做匹配運算的時候,假如

匹配失敗,我們要尋求一個位移,目前我們所知道的條件有:

1、目前的情況下,j指向字符‘b’的位置,也就是3。

2、模式的前3個字符‘a’‘b’‘a’都匹配成功了,也就是說T[i-1]=‘a’;T[i-2]=‘b’;T[i-3]=‘a’。

3、匹配肯定是從i-3的位置開始的。

如果用最暴力的方法,那么把j從新置為0。但是我們注意到j=1的位置的字符和j=3的位置的字符是相同的。也就是說可以

直接從j=1重新開始比較而不是j=0。

通過總結歸納,可以得出:對于模式字符串中的每個字符計算出來的位移就是匹配模式字符串前綴的最長后綴的長度減一

(由于這里采用下標從0計數的方法,所以還要減去1)。

匹配字符串前綴的最長后綴的長度減一。

匹配字符串前綴的最長后綴的長度減一。

這就是KMP算法唯一的奧秘了。

接下來,我們就可以不用考慮帶匹配的字符串的內容,只需要根據模式字符串本身就可以求出每個字符如果匹配失敗后需

要位移的距離。計算完成后我們就可以得到一個整型的數組,數組的長度就是模式字符串的長度,數組中的每個元素就是每個

移動到距離。

為了對模式字符串的每個字符求解移動的距離,可以使用暴力的方法用2個循環的方法求得。仔細一看這又是一個字符串

匹配的方法,只不過匹配對象不一樣了。

這里先別急著求解移動的距離,讓我們先假設我們計算出了每個字符要移動的距離的數組next[],如何來進行字符匹配。


int i=0;
int j=0;
while(i< str.length()-parten.length())
{
  
while(j==0 || parten[j]==str[i])
  
{
    
++i;
    
++j;
  }

  
if(j==parten.length())
    
return true;
  j
=next[j];  //next[]就是計算出來的要移動距離
}


   和前文的程序相比改動灰常灰常的小。再也不需要去改變i的值,當匹配不成功的時候只需要去取出預計算的next[]的值即可。

讓我們回到計算next[]的問題上來。根據前面得出的結論,我們需要找出匹配字符串前綴的最長后綴即可。考察字符串

“aba”,前綴可以是“a”、“ab”。后綴可以是“ba”、“a”。所以對于字符串“aba”的最后一個字母“a”它的next值

就是0。

再考察字符串“ababa”,前綴可以是“a”、“ab”、“aba”、“abab”。后綴可以是“baba”、“aba”、“ba”、

“a”。所以這里匹配的最長后綴是“aba”所以這個next值等于“aba”的長度減一等于2。

如果使用暴力的方法列舉每一個前綴和后綴比較的話,還是會遇到回溯的老問題。對于比較短的模式字符串的話效率尚

可,如果模式字符串的長度比較長的話就不太妙了。

在前面KMP的匹配算法中,由于我們知道了一個next[]數組,就正好知道了j跳轉的值,這里我們同樣可以使用這個方法。

假設在計算每個字符的next值的時候我們也使用2個循環,并且使用i控制下圖中上面的字符串的比較位置,用j控制下圖中下

面字符串的比較位置。

因為我們需要找出匹配前綴的最大的后綴的長度,而對于一個字符串來說前綴和后綴的匹配至少需要相隔一個字符,如下

圖所示:

a

b (i=1)

a

b

a (j=0)

b

a

b

當我們要找出字符串“abab”的最后一個字母‘b’的next值,那么就如同上圖一樣錯開一位,如果不匹配,就把下面一

行的字符串向右再移動一位:

a

b

a

b (i=3)

a

b (j=1)

a

b

這樣就正好匹配,得出next[3]=1。當需要找出字符串“ababb”的最后一個字符next值的時候,是如下圖所示的場景:


a

b

a

b  

b (i=4)

b

a (j=2)

b

a


發現不匹配,此時我們知道上一次匹配是成功的,所以可以讓j直接從上一次匹配成功的位置j=1。


a

b

a

b  

b (i=4)

b (j=1)

b

a

這樣剛好得到匹配的后綴。得出next。

于是可以得出求得next[]的算法:

while (i<len)
{
  
while (j<0 || (i<len && B[i]==B[j]))
  
{
    
++i;
    
++j;
    next[i]
=j;
  }

  j
=next[j];
}

我們注意到,這次比較還是c和a比較,而這次比較在上一次就已經比較過了。所以為了避免這個比較,只需要把next的位于4的位置的值直接設置為next位于2的位置的值即可。那么計算next數組的算法如下:

while (i<len)
{
   
while (j<0 || (i<len && B[i]==B[j]))
   
{
      
++i;
      
++j;
      If(B[i]
==B[j])
         next[i]
=next[j];
      
else
         next[i]
=j;
   }

   j
=next[j];
}


到此,又把數據結構課本上的內容啰唆了一次。
最后是完整的代碼,為了調試方便,加入了不少語句使得算法臃腫了不少。

#define INIT_POSISION 0

int KMP(const char* text,const char* parten_text)
{
    unsigned 
int parten_len=strlen(parten_text);
    unsigned 
int text_len=strlen(text);

    
int* nextArray=new int[parten_len];
    findNext2(parten_text,nextArray);

    
int text_iterator=0;
    
int parten_iterator=0;

    
while (text_iterator<=text_len-parten_len) //如果剩下的字符長度小于模式的長度,就不用匹配了
    {
        
char char_str=text[text_iterator];
        
char char_parten=parten_text[parten_iterator];
        
while (parten_iterator<=INIT_POSISION || (parten_iterator<parten_len && 
            char_str
==char_parten))
        
{
            
++text_iterator;
            
++parten_iterator;
            char_str
=text[text_iterator];
            char_parten
=parten_text[parten_iterator];

        }

        
if (parten_iterator==parten_len) //完全匹配
        {
            
return text_iterator-parten_len-1//返回本次匹配的首字符位置
        }

        
//沒有完全匹配,從next數組取下一個位置重新匹配
        parten_iterator=nextArray[parten_iterator];
    }

    
return INIT_POSISION;
}


void findNext2(const char* B,int* next)
{
    
int len=strlen(B);
    next[ 
0 ] = next[ 1 ] = -1 ;

    
int j=-1;
    
int i=0;
    
while (i<len)
    
{
        
while (j<0 || (i<len && B[i]==B[j]))
        
{
            
++i;
            
++j;
            next[i]
=j;
        }

        j
=next[j];
    }

    
for (int i=0;i<len;++i)
    
{
        cout
<<next[i]<<endl;
    }

}

posted on 2009-03-12 22:46 鍵盤的詠嘆調 閱讀(410) 評論(0)  編輯 收藏 引用 所屬分類: C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美激情久久久久久| 9l国产精品久久久久麻豆| 久久国产精品久久w女人spa| 午夜精品亚洲一区二区三区嫩草| 欧美精品自拍| 亚洲乱码久久| 午夜精品久久久久| 亚洲欧美另类在线| 99热在线精品观看| 国产亚洲精品福利| 欧美天堂亚洲电影院在线观看 | 欧美日韩一级黄| 国产尤物精品| 欧美精品日日鲁夜夜添| 亚洲一区日韩在线| 91久久精品国产| 久久久久久久久久看片| 亚洲久久一区| 亚洲一级网站| 亚洲最新在线视频| 欧美国产第一页| 欧美在线一级va免费观看| 日韩午夜电影av| 亚洲欧美电影院| 蜜桃av一区| 久热国产精品| 久久最新视频| 免费成人高清视频| 欧美jizzhd精品欧美喷水| 亚洲国产三级在线| 国产精品一级在线| 欧美性事免费在线观看| 欧美久久视频| 国产日韩精品综合网站| 国产精品自在欧美一区| 亚洲欧洲精品一区二区精品久久久| 亚洲精品乱码久久久久久| 久久这里有精品15一区二区三区| 欧美日韩国产大片| 久久天天躁狠狠躁夜夜av| 午夜久久资源| 亚洲乱码久久| 久久青草欧美一区二区三区| 久久一本综合频道| 国产精品视频一区二区三区| 欧美吻胸吃奶大尺度电影| 国产综合一区二区| 亚洲欧美在线aaa| 日韩视频不卡中文| 亚洲午夜一区二区| 免费在线观看一区二区| 免费观看成人| 国内免费精品永久在线视频| 欧美亚洲免费电影| 久久亚洲精品视频| 午夜精彩视频在线观看不卡 | 免费国产自线拍一欧美视频| 国产精品一区二区你懂得| 宅男在线国产精品| 欧美一区二区三区在线看| 欧美在线精品一区| 亚洲一区二区在线看| 国产精品h在线观看| 一区二区日韩| 中国亚洲黄色| 裸体女人亚洲精品一区| 欧美日韩亚洲一区二区三区在线 | 欧美日韩免费观看一区=区三区| 免费日韩成人| 伊人婷婷久久| 亚洲午夜精品一区二区| 久久久久久一区| 亚洲人成在线影院| 蜜桃伊人久久| 99热这里只有成人精品国产| 一区二区av| 女人色偷偷aa久久天堂| 最新亚洲一区| 99精品热视频| 国产精品香蕉在线观看| 久久精品人人做人人爽| 亚洲日韩视频| 欧美日韩另类丝袜其他| 亚洲欧美日韩综合一区| 欧美一区二区在线视频| 欧美日本高清视频| 亚洲综合国产| 夜夜夜久久久| 国产视频久久久久| 久久综合久久综合这里只有精品 | 国产自产2019最新不卡| 美女网站久久| 欧美日韩亚洲一区二区| 蜜臀av国产精品久久久久| 欧美第十八页| 国产一级久久| 亚洲国产另类久久精品| 久久久www| 一区二区三区在线观看国产| 亚洲免费在线精品一区| 欧美一级淫片播放口| 中文av一区特黄| 久久久99爱| 在线观看视频免费一区二区三区| 在线观看欧美日本| 亚洲肉体裸体xxxx137| 国产精品亚发布| 亚洲二区精品| 欧美 日韩 国产一区二区在线视频| 欧美日韩免费一区| 久久国产精品高清| 欧美日韩一区综合| 亚洲成人中文| 欧美激情偷拍| 欧美在线网址| 欧美视频在线一区二区三区| 久久久亚洲一区| 国产精品美女午夜av| 欧美一区二区三区日韩视频| 久久午夜电影| 蘑菇福利视频一区播放| 香蕉免费一区二区三区在线观看 | 伊人久久成人| 中文日韩在线视频| 在线亚洲观看| 久久综合狠狠综合久久综合88| 久久国产欧美日韩精品| 99精品欧美一区| 欧美成人午夜77777| 开心色5月久久精品| 国产精品自拍一区| 亚洲视频在线观看网站| 亚洲美女在线观看| 牛牛国产精品| 亚洲电影视频在线| 亚洲电影免费观看高清| 美腿丝袜亚洲色图| 午夜精品久久久| 欧美精品一区二区三区一线天视频| 国产精品地址| 亚洲一区中文| 欧美日韩国产影片| 亚洲乱码国产乱码精品精| 亚洲电影毛片| 欧美激情视频一区二区三区在线播放 | 国内精品美女在线观看| 一区二区三区欧美在线观看| 亚洲图片在线观看| 国产精品高潮视频| 亚洲视频网在线直播| 午夜日韩av| 国产毛片一区| 久久久久久久综合日本| 久久综合中文色婷婷| 亚洲国产日韩欧美一区二区三区| 91久久精品一区二区别| 亚洲电影免费观看高清完整版在线观看| 牛夜精品久久久久久久99黑人| 久久综合影音| 欧美成人免费在线| 亚洲美女在线看| 国产精品电影在线观看| 亚洲欧美日本国产有色| 伊人久久亚洲美女图片| 久久精品麻豆| 欧美激情亚洲另类| 亚洲欧美一区在线| 好吊妞**欧美| 亚洲欧美中文日韩v在线观看| 亚洲第一区色| 欧美日本国产精品| 亚洲一级免费视频| 欧美日本一区二区三区| 一区二区三区日韩精品| 久久久久国内| 国产亚洲成年网址在线观看| 久久久www| 中文网丁香综合网| 亚洲电影自拍| 久久久视频精品| 久久综合久久美利坚合众国| 国产精品家庭影院| 久久九九99| 一区二区国产日产| 你懂的亚洲视频| 久久本道综合色狠狠五月| 亚洲欧洲日本国产| 国产综合色精品一区二区三区| 亚洲精品国产精品乱码不99| 亚洲欧美电影院| 亚洲精品极品| 欧美高清在线| 亚洲精品午夜| 欧美激情91| 久久蜜臀精品av| 久久亚洲国产成人| 国产亚洲激情| 欧美日韩免费一区| 欧美激情精品久久久久久蜜臀| 两个人的视频www国产精品|