題目描述
請實現一個函數用來匹配包括'.'和'*'的正則表達式。模式中的字符'.'表示任意一個字符,而'*'表示它前面的字符可以出現任意次(包含0次)。 在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"ab*ac*a"匹配,但是與"aa.a"和"ab*a"均不匹配。
分析:
首先,考慮特殊請況:
- 兩個字符串都爲空,返回true.
- 當第一個字符串不空,而第二個字符串空了,返回false(因爲這樣,就無法匹配成功了,而如果第一個字符串空了,第二個字符串非空,還可能匹配成功的。Eg: a*a*a*a*)
正常情況:每次分別在str和pattern中取一個字符進行比較,如果匹配,則匹配下一個字符,否則,返回不匹配。
分析:遞歸實現
設匹配遞歸函數 match(str, pattern)。
1. 如果模式匹配字符的下一個字符是‘*’:
如果pttern當前字符和str的當前字符匹配,:有以下三種可能情況
- pttern當前字符能匹配 str 中的 0 個字符:match(str, pattern+2)
- pttern當前字符能匹配 str 中的 1 個字符:match(str+1, pattern+2)
- pttern當前字符能匹配 str 中的 多 個字符:match(str+1, pattern)
如果pttern當前字符和和str的當前字符不匹配:
- pttern當前字符能匹配 str 中的 0 個字符:(str, pattern+2)
2. 如果模式匹配字符的下一個字符不是‘.’:
對於 ‘.’ 的情況比較簡單,’.’ 和一個字符匹配 match(str+1, pattern+1)
3. 如果模式匹配字符的下一個字符是正常字符,且 *str == *pattern,
遞歸下一個字符 :match(str+1, pattern+1)
實現
注:上邊這幾類情況,再代碼實現中,可以進行歸類合併,詳見下面的代碼:
//正則表達式的匹配
//注:空字符串和“.*”是匹配的
bool match(char* str, char* pattern)
{
//特殊情況處理
//如果str和pattern都爲NULL, 返回true
if(*str == '\0' && *pattern == '\0')
{
return true;
}
//str不爲NULL, pattern爲NULL,一定不匹配,返回false.
//注:str爲NULL, pattern不爲NULL時,可能匹配。 eg: a*a*a*a*
if(*str != '\0' && *pattern == '\0')
{
return false;
}
//遞歸進行處理(正常情況)
if(*(pattern+1) == '*') //pattern可匹配0次,1次或多次
{
if(*pattern == *str || (*str != '\0' && *pattern == '.'))
{
return match(str,pattern+2) //*pattern == *str請況下,匹配0個
|| match(str+1,pattern); //匹配多個
}
else //*pattern != *str請況下匹配0次,pattern+2
{
return match(str,pattern+2);
}
}
//pattern下一個字符爲. 或正常字符即(*str == *pattern)
if((*str != '\0' && *pattern == '.') || (*str == *pattern))
{
return match(str+1, pattern+1);
}
return false;
}
總結
在寫這道題時,首先理解什麼是正則表達式,對“*”和“.”的匹配模式進行理解,然後對各種情況進行分析,歸類。再具體寫代碼實現。
圖解