帶萬用字元的字串匹配問題的動態規劃演算法

2021-06-20 18:33:50 字數 3293 閱讀 6874

字串匹配問題,給定一串字串,按照指定規則對其進行匹配,並將匹配的結果儲存至output陣列中,多個匹配項用空格間隔,最後乙個不需要空格。

要求:1.        匹配規則中包含萬用字元?和*,其中?表示匹配任意乙個字元,*表示匹配任意多個(>=0)字元。

2.        匹配規則要求匹配最大的字元子串,例如a*d,匹配abbdd而非abbd,即最大匹配子串。

3.        匹配後的輸入串不再進行匹配,從當前匹配後的字串重新匹配其他字串。

我們先考慮rule是否匹配input某乙個字首的情況的情況

設狀態dp[i][j]為rule[i]與input[j]是否匹配(true或false)

分別考慮rule[i]==?,*以及普通字元的情況

rule[i]='*'

時:1.      dp[i][j-1]==true能推出di[i][j]==true但是dp[i][j-1]==false不能推出dp[i][j]==false(考慮rule[0...i]=abc*和input[0...j-1]=ab且input[j]=c。所以不能用dp[i][j-1]

2.      應該用dp[i-1][j]和dp[i-1][j-1]。其實是一樣的,因為dp[i-1][k]=true即可推出dp[i][j]=true(其中0<=k<=j)。否則就是false。即dp[i][j]與dp[i-1][k]的或等價。

rule[i]='?'

時:1.      dp[i][j-1]和dp[i-1][j]都不能推斷出dp[i][j]。比如dp[i][j-1]=ture時,如果rule[0…i]都是普通字元,則明顯dp[i][j]=false。但是如果rule[0…i]=*時,則明顯dp[i][j]也是true。同理dp[i-1][j]也不能(分別考慮rule[0…i-1]是普通字串和是*的情況)

2.      dp[i-1][j-1]與dp[i][j]是無條件等價的,可以分別考慮dp[i-1][j-1]=true或false的情況。

rule[i]

為普通字元時:

1.  同rule[i]==』?』一樣,無法通過dp[i][j-1]和dp[i-1][j]推斷出dp[i][j]

2.  (dp[i-1][j-1]&&rule[i]==input[j])與dp[i][j]等價。

設rule,input都從1開始:

初始化:

dp[0][1….j_len]=flase

dp[1…i_len][0]=false

dp[0][0]=true.

動態規劃遞迴式為:

1.      rule[i]==』*』:dp[i][j]=(dp[i-1][k]的或,k=0…j)

2.      rule[i]!=』*』:dp[i][j]=(dp[i-1][j-1]&&(rule[i]==input[j]||rule[i]=』?』))

從該題得到的思考:

動態規劃的遞迴式需要是充分必要條件:

充分:

即當滿足遞迴式時,一定能給出正確的結果。在該題中,即當rule=』?』且dp[i-1][j-1]=ture時dp[i][j]一定是ture。

必要性:

所有結果都能通過該遞迴式得到,不能有遺漏。即完備性。

動態規劃的完備性其實很好證明,比如在本題中,只要考慮rule[i]的3種可能取值和將dp[i][j]表填滿就行了。即rule=』?』時,雖然dp[i][j-1]和dp[i-1][j]不能用,但是可以通過dp[i-1][j-1]就可以得出結果,加上初始化的值,就可以得出整個dp表的值。

以上是快速判斷rule是否與input匹配的演算法。但是題目其實是要知道rule是否與input的某一子段匹配,乙個方法就是遍歷以input[0]到input[len]開頭的所有子串。即在外面再加一層迴圈。複雜度是(rule_len)*(input_len)^2。

但是其實改一下狀態設定就可以直接用動態規劃解決。

設狀態dp[i][j]為rule[0…i]匹配以input[j]結尾的input字串的最大長度

分別考慮rule[i]==?,*以及普通字元的情況如上

rule[i]='*'

時:

若dp[i-1][k]!=-1,則dp[i-1][k]+j-k就是dp[i][j]

當然,得從眾多的k中選乙個最大的,即dp[i][j]=max

rule[i]='?'

時:rule[i]

為普通字元時:

rule[i]必須與input[j]對應上,而且要想將rule[0…i]都匹配上,dp[i-1][j-1]就不能等於-1,即必須匹配。

即dp[i-1][j-1]!=1且rule[i]與input[j]匹配(rule[i]==input[j]||rule[i]=』?』)

設rule,input都從1開始:

初始化:

dp[0][1….j_len]=0

dp[1…i_len][0]=-1

dp[0][0]=0

動態規劃遞迴式為:

3.      rule[i]==』*』:dp[i][j]=max(dp[i-1][k]+j-k)0<=k<=j且dp[i-1][k]!=-1)

4.      rule[i]!=』*』:dp[i][j]=(dp[i-1][j-1]!=-1&&(rule[i]==input[j]||rule[i]=』?』))?dp[i-1][j-1]+1:-1;

其中初始化的dp[0][1….j_len]=0很重要。例如rule=」n」,input=」nsn」。當n匹配到nsn的第二個n時,就是求dp[1][3]時,要看dp[0][2],如果dp[0][2]=-1,則意味著rule中n字母之前的就已經不匹配,所以該n也不能匹配。但是很明顯,n之前沒有字母需要匹配,即要把dp[0][0…len]這種特殊情況摘出來。即不需要考慮之前是否匹配(因為不需要),從新開始匹配。

帶萬用字元的字串匹配 動態規劃

描述 萬用字元是一類鍵盤字元,當我們不知道真正字元或者不想鍵入完整名字時,常常使用萬用字元代替乙個或多個真正字元。萬用字元有問號 和星號 等,其中,可以代替乙個字元,而 可以代替零個或多個字元。你的任務是,給出乙個帶有萬用字元的字串和乙個不帶萬用字元的字串,判斷他們是否能夠匹配。例如,1?456 可...

帶萬用字元的字串匹配

05 帶萬用字元的字串匹配 描述萬用字元是一類鍵盤字元,當我們不知道真正字元或者不想鍵入完整名字時,常常使用萬用字元代替乙個或多個真正字元。萬用字元有問號 和星號 等,其中,可以代替乙個字元,而 可以代替零個或多個字元。你的任務是,給出乙個帶有萬用字元的字串和乙個不帶萬用字元的字串,判斷他們是否能夠...

OpenJudge 帶萬用字元的字串匹配

萬用字元是一類鍵盤字元,當我們不知道真正字元或者不想鍵入完整名字時,常常使用萬用字元代替乙個或多個真正字元。萬用字元有問號 和星號 等,其中,可以代替乙個字元,而 可以代替零個或多個字元。你的任務是,給出乙個帶有萬用字元的字串和乙個不帶萬用字元的字串,判斷他們是否能夠匹配。例如,1?456 可以匹配...