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

鍵盤的詠嘆調(diào)

常用鏈接

統(tǒng)計(jì)

最新評(píng)論

KMP算法

   傳統(tǒng)的字符串匹配算法中,為了在一段字符串中查找模式字符串的話需要使用2個(gè)循環(huán)嵌套起來,例如:
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;

   

這種方法很黃很暴力,其中對(duì)于第一個(gè)循環(huán),會(huì)產(chǎn)生回溯。也就是說如果一個(gè)字符串:

bacbababaabcba來匹配模式字符串a(chǎn)bababa。當(dāng)原字符串的a和模式字符串的c做比較的時(shí)候,

b

a

c

b

a

b

a

b

a

a

(i=9)

b

c

b

a

a

b

a

b

a


(j=5)

a

當(dāng)發(fā)現(xiàn)不匹配的時(shí)候i會(huì)往前遞進(jìn)一位,此時(shí)從原字符串的第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算法中

 

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

的可能,現(xiàn)在的問題是如何求這個(gè)位移?

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

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

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

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

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

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

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

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

(由于這里采用下標(biāo)從0計(jì)數(shù)的方法,所以還要減去1)。

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

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

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

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

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

移動(dòng)到距離。

為了對(duì)模式字符串的每個(gè)字符求解移動(dòng)的距離,可以使用暴力的方法用2個(gè)循環(huán)的方法求得。仔細(xì)一看這又是一個(gè)字符串

匹配的方法,只不過匹配對(duì)象不一樣了。

這里先別急著求解移動(dòng)的距離,讓我們先假設(shè)我們計(jì)算出了每個(gè)字符要移動(dòng)的距離的數(shù)組next[],如何來進(jìn)行字符匹配。


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[]就是計(jì)算出來的要移動(dòng)距離
}


   和前文的程序相比改動(dòng)灰常灰常的小。再也不需要去改變i的值,當(dāng)匹配不成功的時(shí)候只需要去取出預(yù)計(jì)算的next[]的值即可。

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

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

就是0。

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

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

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

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

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

假設(shè)在計(jì)算每個(gè)字符的next值的時(shí)候我們也使用2個(gè)循環(huán),并且使用i控制下圖中上面的字符串的比較位置,用j控制下圖中下

面字符串的比較位置。

因?yàn)槲覀冃枰页銎ヅ淝熬Y的最大的后綴的長度,而對(duì)于一個(gè)字符串來說前綴和后綴的匹配至少需要相隔一個(gè)字符,如下

圖所示:

a

b (i=1)

a

b

a (j=0)

b

a

b

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

行的字符串向右再移動(dòng)一位:

a

b

a

b (i=3)

a

b (j=1)

a

b

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


a

b

a

b  

b (i=4)

b

a (j=2)

b

a


發(fā)現(xiàn)不匹配,此時(shí)我們知道上一次匹配是成功的,所以可以讓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比較,而這次比較在上一次就已經(jīng)比較過了。所以為了避免這個(gè)比較,只需要把next的位于4的位置的值直接設(shè)置為next位于2的位置的值即可。那么計(jì)算next數(shù)組的算法如下:

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];
}


到此,又把數(shù)據(jù)結(jié)構(gòu)課本上的內(nèi)容啰唆了一次。
最后是完整的代碼,為了調(diào)試方便,加入了不少語句使得算法臃腫了不少。

#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數(shù)組取下一個(gè)位置重新匹配
        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 鍵盤的詠嘆調(diào) 閱讀(410) 評(píng)論(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>
            欧美国产日韩免费| 亚洲区第一页| 久久综合五月| 久久久综合激的五月天| 欧美专区日韩专区| 久久成人人人人精品欧| 久久精品中文字幕免费mv| 久久精品国产精品亚洲精品| 久久久之久亚州精品露出| 久久躁狠狠躁夜夜爽| 玖玖玖国产精品| 欧美精品久久久久久| 欧美视频在线不卡| 国产精品毛片一区二区三区 | 欧美黑人国产人伦爽爽爽| 欧美激情一区二区久久久| 欧美日韩另类视频| 国产亚洲欧美日韩日本| 亚洲理论电影网| 午夜精品视频一区| 麻豆精品在线观看| 中文有码久久| 久久婷婷一区| 欧美色大人视频| 国语自产偷拍精品视频偷| 亚洲精品乱码久久久久久按摩观| 亚洲视频在线二区| 免费不卡在线观看| 亚洲性线免费观看视频成熟| 久久久国产精彩视频美女艺术照福利 | 夜久久久久久| 久久久久成人精品免费播放动漫| 亚洲成人在线网站| 亚洲最新视频在线| 久热精品视频在线观看| 国产欧美日本| 亚洲视频日本| 欧美护士18xxxxhd| 欧美影院一区| 国产老女人精品毛片久久| 99国产欧美久久久精品| 久久婷婷麻豆| 亚洲欧美日韩一区二区在线 | 久久国产精品久久久久久久久久| 欧美精品免费视频| 亚洲成人在线免费| 欧美一二区视频| 国产精品日韩一区二区三区| 亚洲另类春色国产| 欧美高清视频| 久久嫩草精品久久久久| 国产精品青草久久| 宅男噜噜噜66国产日韩在线观看| 欧美成年人网| 美女网站久久| 亚洲成色www久久网站| 久久久久五月天| 欧美一区二区三区久久精品茉莉花| 欧美午夜免费电影| 亚洲淫性视频| 亚洲私人影吧| 国产欧美成人| 久久电影一区| 羞羞漫画18久久大片| 国产欧美综合在线| 久久精品国产v日韩v亚洲| 亚洲欧美日韩精品综合在线观看| 国产精品国产三级国产普通话蜜臀| 99热这里只有成人精品国产| 亚洲精品一区二区在线| 欧美日韩国产欧| 亚洲视频精选在线| 亚洲一区影院| 精品成人a区在线观看| 免费视频久久| 欧美电影免费网站| 中日韩美女免费视频网址在线观看 | 99国产精品| 在线视频你懂得一区二区三区| 欧美日韩一区二区高清| 性欧美videos另类喷潮| 久久丁香综合五月国产三级网站| 又紧又大又爽精品一区二区| 欧美激情网友自拍| 国产精品户外野外| 久久久久免费观看| 欧美精品一区二| 欧美一区二区三区视频在线观看| 久久大香伊蕉在人线观看热2| 亚洲国产一区二区三区高清 | 亚洲一区二区欧美| 欧美影院在线| 一本大道av伊人久久综合| 亚洲一二区在线| 136国产福利精品导航| 国产精品99久久不卡二区| 黄色一区二区三区| 一区二区三区四区蜜桃| 国产精品视屏| 性做久久久久久久久| 久久综合久久美利坚合众国| 中文欧美日韩| 欧美国产日韩一区二区三区| 欧美日韩国产在线看| 久久精品国产99国产精品澳门| 美腿丝袜亚洲色图| 欧美伊久线香蕉线新在线| 欧美aa国产视频| 欧美一区在线看| 欧美黄在线观看| 久久中文字幕一区二区三区| 欧美午夜不卡视频| 亚洲人成久久| 在线欧美影院| 久久av老司机精品网站导航| 亚洲一区二区黄| 欧美精品在线视频| 欧美激情一区二区三区在线视频观看 | 国产美女精品在线| 亚洲久久一区| 亚洲精品在线看| 久久精品视频在线播放| 午夜亚洲福利| 欧美片在线观看| 亚洲高清一区二区三区| 极品日韩av| 久久精品国产亚洲一区二区| 性欧美1819sex性高清| 国产精品久久久对白| 日韩一级裸体免费视频| 99www免费人成精品| 欧美国产国产综合| 亚洲二区精品| 亚洲精品视频啊美女在线直播| 久久男人资源视频| 欧美国产一区二区| 亚洲啪啪91| 欧美欧美在线| 亚洲日本视频| 一区二区高清在线| 欧美日韩在线精品| 一区二区高清| 欧美一区二区免费| 好吊色欧美一区二区三区视频| 欧美中文日韩| 欧美成人黑人xx视频免费观看| 在线国产日韩| 欧美二区视频| 亚洲美女视频在线观看| 亚洲午夜精品网| 国产精品一卡二卡| 欧美在线观看一区二区| 毛片基地黄久久久久久天堂| 亚洲国产精品va在线观看黑人| 美女视频一区免费观看| 亚洲人体一区| 亚洲女女女同性video| 国产精品毛片| 久久久精品网| 亚洲精品久久久久久久久久久| 亚洲视频999| 韩国av一区二区| 欧美精品久久天天躁| 亚洲一区二区在线| 麻豆成人在线播放| 99精品免费视频| 性做久久久久久久免费看| 老司机午夜精品| 99re视频这里只有精品| 国产日产欧美一区| 欧美91福利在线观看| 亚洲尤物视频在线| 亚洲大片精品永久免费| 亚洲欧美中文字幕| 亚洲国产精品一区二区久| 国产精品v欧美精品v日韩精品| 久久国产精品毛片| 一区二区三区你懂的| 欧美高清视频在线| 久久电影一区| 亚洲图片欧洲图片av| 亚洲第一二三四五区| 国产精品久久久久久久久借妻 | 国产酒店精品激情| 欧美韩日一区二区| 久久伊人免费视频| 亚洲欧美日韩综合| 亚洲伦理精品| 亚洲成在线观看| 久久久xxx| 亚洲综合日韩在线| 日韩一区二区福利| 亚洲激情小视频| 国产综合在线看| 国产精品久久久久影院亚瑟| 欧美大片专区| 美女91精品| 久久综合福利| 久久久国产精彩视频美女艺术照福利| 在线亚洲激情|