劍指offer:正則表達式匹配


題目

題目鏈接
劍指offer:正則表達式匹配
題目描述
請實現一個函數用來匹配包括'.'和'*'的正則表達式。模式中的字符.表示任意一個字符,而*表示它前面的字符可以出現任意次(包含0次)。 在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"ab*ac*a"匹配,但是與"aa.a"和"ab*a"均不匹配。

解題思路

1.分析題目

  • 輸入:一個待匹配字符串,一個待匹配正則表達式
  • 輸出:字符串與正則表示式相匹配則輸出true,否則輸出false
  • 條件:正則表達式中僅含兩個特殊字符;.表示任意一個字符,*表示它前面的字符能夠出現0~無數次。題目未說明是否貪心匹配(即盡可能多的匹配)的情況下,應默認非貪心匹配。即應考慮類似aaaa*aa相匹配的情況。同時注意可能會出現.*這類能夠匹配所有字符的表達式。

2.可能出現的情況
考慮字符串和正則相匹配時能夠相消去,則當最終兩者為空時為匹配成功;中途有不匹配且不帶*的字符或是最終不能相互消去時為匹配失敗。這種情況很顯然使用指針移動特別好用。
考慮情況如下:

  • 字符串空時,正則式不為空。后者剩余字符若皆為帶/*字符,則應繼續消去。
  • 當前指針指向字符能夠消去時(正則式當前指針字符與字符串當前指針字符相同,或是正則式當前指針字符為.且字符當前指針不為\0),需要考慮正則指針的下一步指向是否為*。為*則需要考慮此時是否非貪心匹配。
  • 當前指針指向字符不可相互消去時,需考慮正則指針下一步指向是否為*,為*則可忽略正則指針此時的不匹配字符,令其向前移兩位;否則直接匹配失敗。例如aaaab*c*aa能匹配成功。

3.思考解題步驟
在2中所考慮的情況都能夠用起初的思路--指針移動解決,故確定以指針為解題方向。
同時,每一步對於當前指針指向字符的處理過程都是相似的,故考慮使用遞歸使代碼更加簡潔。
很慚愧,在編寫2中指針字符相互消去的情況時,我發現自己寫的代碼總是會遺漏部分情況,查看錯誤樣例后發現對*的非貪心匹配處理要寫出大量邏輯繁瑣且容易出錯的代碼。在查看討論區的解答后,發現自己一直走了死胡同。對於這種問題應考慮使用動態規划的思想,將情況一分為二的處理,分別計算繼續判斷當前*與結束當前*匹配的情況。

具體代碼

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if (*str == '\0' && *pattern == '\0')
                return true;
        // 1.匹配帶*正則(包括非貪心情況)
        if (*str == *pattern || (*pattern == '.' && *str != '\0'))
        {
            // 不是正則式
            if (*(pattern + 1) != '*')
                return match(++str, ++pattern);
            // 是正則式
            // 將*字符的匹配一分為二的處理
            return match(str, pattern + 2) || match(str + 1, pattern);
        }
        // 消去無用帶*字符
        else if (*(pattern + 1) == '*')
        {
            pattern += 2;
            return match(str, pattern);
        }
        return false;
    }
};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM