萬用字元的字串匹配演算法

2021-07-02 02:26:30 字數 3241 閱讀 2638

1. 簡述

題目描述:

str1中可能包含的字元:除了'*'和'?'以外的任意字元。

str2中可能包含的字元:任意字元。其中,'?'表示匹配任意乙個字元,'*'表示匹配任意字元0或者多次。

給出這樣兩個字串,判斷str2是否是str1的子串,如果是輸出第乙個匹配到的子串,如果不是,輸出"不是子串"。

2. 分析

對於'?'的處理,只要在匹配的時候將**由:if(str1[i]==str2[j]) 改為 if(str1[i]==str2[j] || str2[j]=='?')即可。

對於'*'的處理,可以將str2根據其中的'*'分為若干個片段,然後依次在str1中分別匹配這幾個片段即可,而且對於這幾個片段分別匹配,如果第k個片段在str1中匹配不到,後面也可以結束了。這裡舉例說明一下:對於str1="oh year.totay is weekend!",str2=*ye*a*e*",實際上就是在str1中匹配"ye","a","e"這三個片段。

oh year.totay is weekend!

yea                e

yea                  e

yea                     e

ye         a        e

ye         a         e  

ye         a             e

實際上,能夠匹配到上面6種情況,按照我們的如果從左到右的匹配每個片段返回的是第一種情況。這裡主要分析這種情況的處理,對於所有情況的輸出後面再簡單說明一下。

首先處理str2,根據'*'分成若干個部分,然後依次在str1中進行匹配,使用kmp演算法即可。這樣判斷能否匹配或者只找第乙個匹配的子串的負責度是o(m+n)

3. **實現

其中利用了kmp演算法,為了使用方便,稍微改了下kmp演算法的輸入引數,即pat字串的長度不用'\0'確定,用指定引數確定。

[cpp]view plain

copy

print?

#include 

#include 

using

namespace

std;  

// kmp演算法,pat長度由len_pat指定 

void

get_next(

const

char

pat, 

intnext, 

intpat_len)   

for(

inti=0; i

if(pat[i] == pat[next[i]])  

next[i] = next[next[i]];  

}  }  

// kmp演算法,str長度由'\0'判斷,pat長度由len_pat指定 

intkmp_next(

const

char

text, 

const

char

pat, 

intpat_len)   

delete

next;  

return

t}  

// 切分pat的結構 

struct

pat_info ;  

// 可以匹配萬用字元的kmp,返回第乙個匹配子串在str中的下標 

void

kmp_wildcard(

char

* str, 

char

* pat)   

else

else

}  } // for

// 測試切分結果 

/* while(store.size() > 0) */

// 根據切分後的pat序列進行匹配

intfirst_index = -1; 

// 起始的下標 

intlast_index = 0; 

// 最後的下標後面的乙個位置 

intnext_index = 0; 

// 下一次開始匹配的下標 

4. 所有匹配結果輸出

例子:oh year.totay is weekend!

yea                e

yea                  e

yea                     e

ye         a        e

ye         a         e  

ye         a             e

首先是所有結果是什麼:如果我們要的是str1匹配到的字串,那麼可見實際上上面6個有3個是重複的,因此對於這種情況,只有得到匹配字串在str1中的開始index和結束index,然後對於重複的去掉即可。如果要的是str1匹配到的字元的下標,那麼這是不會重複的。

然後說一下匹配方法,基本上與匹配乙個的差不多,不過要加上回溯的過程。比如第一次匹配成功後,繼續在新的位置匹配最後乙個片段,如果成功了就是第二次匹配成功了,否則就要回溯取在新的位置去匹配倒數第二個片段了,依次類推。直到第乙個片段都沒法再匹配到,不再回溯了。此外值得注意的是,如果第一次匹配都沒成功,就不必回溯了,這種情況下,說明不可能存在匹配結果,因為匹配是從左到右的順序,都會盡量在左邊找到合適的片段,如果第一次都沒成功,假設在第k個片段上匹配失敗了,那麼再回溯的話,輪到k片段是空間實際上只會與上次相同或者更小,大的空間都匹配不到,小的空間更不用說了。

還有一點值得注意:有的一些博文採用的是用str2中乙個字元乙個字元的匹配,感覺效率會低,而且也沒有片段這個方法中的第一次匹配失敗就可以停止的規律,也用不了kmp(準確的說是體現不出kmp的優勢)。

5. 參考

帶萬用字元*的字串匹配    

hdu 3901 wildcard 帶萬用字元的字串匹配    

萬用字元匹配字串

問題 實現支援?和 兩個萬用字元的字串匹配函式。implement wildcard pattern matching with support for and matches any single character.matches any sequence of characters inclu...

帶有萬用字元的字串匹配演算法 C C

日前某君給我出了這樣一道題目 兩個字串,乙個是普通字串,另乙個含有 和?萬用字元,代表零個到多個任意字元,代表乙個任意字元,萬用字元可能多次出現。寫乙個演算法,比較兩個字串是否相等。我花了四個小時寫出兩種演算法來解決這個問題,簡單地測試了一下,好使!方法一,從無萬用字元到有?再到有 逐步推進分析 c...

含有萬用字元的字串匹配

字串匹配問題,給定兩個字串,求字串2,在字串1中的最先匹配結果。字串2中可以存在 符號,且該符號可以代表任意字元,即字串2中存在萬用字元。e.g.輸入 abcdefghabef,a f 輸出 abcdef include include using namespace std bool match ...