《劍指offer》:[53]正則表達式匹配

題目:請實現一個函數用來匹配包括’.’和’‘的正則表達式。模式中的字符’.’表示任意一個字符,而’‘表示它前面的字符可以出現任意次(包含0次)。在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串”aaa”與模式”a.a”和”ab*ac*a”匹配,但是與”aa.a”和”ab*a”均不匹配。
   分析;常規中,如果是普通的兩個字符串,那很簡單,我們直接進行對比就可以了,這裏又是要求匹配是指字符串的所有字符匹配整個模式,所以只要直接挨個比較就可以了,如果都相等則返回true;否則返回false;可是這個題目來了一個'.'和'*'兩個比較煩人的東西,它改變了遊戲的規則。把遊戲變的複雜多變。
   首先要明確'.'確定了字符的個數爲1,並且爲任意;'*'可以確定它前面的字符的個數包括0次;
   第一種情況:當模式的第二個字符不是'*'的時候,如果字符串的第一個字符和模式串的第一個字符相等,則都向後移動一個,匹配剩下的字符串和模式串。如果不等則直接返回false;
    第二種情況:當模式的第二個字符是'*'的時候,這時候就稍複雜點兒,因爲這時候存在不同的幾種匹配方式:以字符串"aaa"與模式"ab*ac*a"匹配爲例:
1、如果模式串中的字符和字符串中的字符不等如(a),且模式串的第二個字符爲'*'。

      選擇只有一種:在模式串上向後移動兩個字符,忽略掉b和*,因爲'*'可以匹配0個字符;如下圖:


2、如果模式串中的字符和字符串中的字符相等如(b),或者模式串中爲'.'如(c),並且模式串的第二個字符爲'*'。其實(b)和(c)是一樣的。這時候選擇有三種情況:
     (1)可以選擇在模式串上向後移動兩個字符,忽略掉b和*,因爲'*'可以匹配0個字符,字符串str保持不變;
     (2)可以選擇越過'*','*'前的a當作有效的字符,且數量爲1,str++;
     (3)可以選擇模式串pattern不變,因爲‘*’前的a可以任意數量的,並且和字符串str相等,只需要str++即可;

具體如下圖所示:


具體實現代碼如下:
#include <iostream>
using namespace std;
bool MatchCore(char *str,char *pattern)
{
	if(*str=='\0' && *pattern=='\0')
		return true;
	if(*str!='\0' && *pattern=='\0')
		return false;
	if(*(pattern+1)=='*')
	{
		if(*pattern==*str || (*pattern=='.' && *str!='\0'))//將‘*’號忽略,‘*’前的作爲一個有效的值;
			return MatchCore(str+1,pattern+2) 
			|| MatchCore(str+1,pattern) //‘*’號前可以出現任意個,所以pattern可以保持不變
			|| MatchCore(str,pattern+2);//忽略‘*’及‘*’號以前的字符;
		else
			return MatchCore(str,pattern+2);//因爲‘*’ 號前的字符與*str不等,所以只能忽略*pattern字符一個選擇;
	}
	if(*str==*pattern || (*pattern=='.' && *str!='\0'))
		return MatchCore(str+1,pattern+1);//正常的字符串比較;
	return false;
}
bool match(char *str,char *pattern)
{
	if(str==NULL || pattern==NULL)
		return false;
	return MatchCore(str,pattern);
}
int main()
{
	char str[]="aaa";
	char *pattern[4]={"a.a","ab*ac*a","aa.a","ab*a"};
	for(int i=0;i<4;i++)
	{
		if(match(str,pattern[i]))
			cout<<"The same!"<<endl;
		else
			cout<<"Not the same!"<<endl;
	}
	system("pause");
	return 0;
}

運行結果:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章