題目以下:正則表達式
給你一個字符串 s 和一個字符規律 p,請你來實現一個支持 '.' 和 '*' 的正則表達式匹配。spa
'.' 匹配任意單個字符
'*' 匹配零個或多個前面的那一個元素
所謂匹配,是要涵蓋 整個 字符串 s的,而不是部分字符串。code
示例 1:blog
輸入:s = "aa" p = "a"
輸出:false
解釋:"a" 沒法匹配 "aa" 整個字符串。
示例 2:ip
輸入:s = "aa" p = "a*"
輸出:true
解釋:由於 '*' 表明能夠匹配零個或多個前面的那一個元素, 在這裏前面的元素就是 'a'。所以,字符串 "aa" 可被視爲 'a' 重複了一次。
示例 3:字符串
輸入:s = "ab" p = ".*"
輸出:true
解釋:".*" 表示可匹配零個或多個('*')任意字符('.')。
示例 4:string
輸入:s = "aab" p = "c*a*b"
輸出:true
解釋:由於 '*' 表示零個或多個,這裏 'c' 爲 0 個, 'a' 被重複一次。所以能夠匹配字符串 "aab"。
示例 5:class
輸入:s = "mississippi" p = "mis*is*p*."
輸出:false
di
提示:動態規劃
0 <= s.length <= 20
0 <= p.length <= 30
s 可能爲空,且只包含從 a-z 的小寫字母。
p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。
保證每次出現字符 * 時,前面都匹配到有效的字符
初始思路:
剛開始的解題思路想的是挨個對比兩個字符串,而後分三種不一樣的狀況進行處理,分別是:
1)非特殊字符比較:
1.1)後爲*號字符,且當前字符相等,這種狀況太複雜了,要挨個枚舉當前字符匹配的次數;
1.2)後不爲*號字符,且當前字符相等,這種狀況直接返回false;
1.3)兩字符不相等,且後續爲*號,則直接忽略當前字符和*號,進行剩餘字符的比較。
2)當前字符爲.:等同於非特殊符號相等的狀況。
3)當前爲*號,這個比較難處理,當時沒想出來,這道題也所以沒作出來。
答案思路:答案使用了動態規劃來解題。
和個人分類不一樣,不過有點共通的地方。按照*號來進行分類。
1)當前字符爲*號,此時分爲兩種狀況;
1.1)此*號不起匹配做用。
1.2)當前*號進行一次匹配,同時*號繼續發揮做用。
2)當前字符不爲*號,則按照非特殊字符的狀況直接進行比較便可;
代碼以下:
/*進行字符的比較*/
bool matchChar(string & s, string & p,int i, int j) { if(i<0) { return false; }
/*匹配任意字符*/ if(p[j]=='.') { return true; } return s[i]==p[j]; } bool isMatch(string s, string p) { int m=s.size(),n=p.size();
/*注意這裏須要分開理解,vecDp[i][j]表示的是S的前i個字符與P的前j個字符匹配;後面進行字符匹配時,要注意下標的選擇*/ vector<vector<int>> vecDp(m+1,vector<int>(n+1)); vecDp[0][0]=1; for(int i=0;i<=m;i++) { for(int j=1;j<=n;j++) {
/*對應的第一種狀況*/ if(p[j-1]=='*') {
/*注意這裏是|=運算符*/ vecDp[i][j]|=vecDp[i][j-2]; if(matchChar(s,p,i-1,j-2)) {
/*同上,注意這裏是|=運算符*/ vecDp[i][j]|=vecDp[i-1][j]; } }
/*對應的第二種狀況*/ else { if(matchChar(s,p,i-1,j-1)) { vecDp[i][j]=vecDp[i-1][j-1]; } } } } return vecDp[m][n]; }