Leetcode 10 Regular Expression Matching

leetcode 10 Regular Expression Matching

简介

此题让实现一个简单的正则表达式。
该表达式只需要有如下功能

  • a 匹配字符 'a'
  • a* 匹配零或多个 a
  • .匹配任意字符
  • .* 匹配零或多个任意字符

思路

把正则式分解,

  • 单字符通配为一类,如'a','b','.'
  • 若干通配为一类,如 'a','.'

当拿到一个 待匹配字符 varChar 和一个正则字符 reg 后,
如果当前正则字符是单字符通配

  • 若二者匹配,继续匹配下一个字符和下一个正则字符
  • 若二者不匹配,即返回不匹配
    如果当前正则字符是若干通配
  • 若二者匹配,可能有以下几种情况
    • 下一个字符与下一个正则字符匹配
    • 下一个字符与当前正则字符匹配
  • 若二者不匹配,有两种可能
    • 不匹配
    • 当前若干通配符匹配0个字符,继续匹配当前字符和下一个正则符

终止时,

  • 如果正则串到尾部,而待匹配串未到尾部说明匹配失败
  • 如果待匹配串到尾部,而正则串未到尾部,则
    • 如果正则串后面(匹配0个)都是若干通配符匹配成功
    • 如果后面有单字符通配符则匹配失败
  • 如果正则串和待匹配串都到尾部说明匹配成功

实现

AC的代码是用递归实现的。效率很差,需要运行1000ms。

#include <string>
#include <vector>
#include <iostream>

using namespace std;

// . -> char
// .* -> n*char
// x -> x
// x* -> x * n
class Solution
{
private:
    vector<string> parsedPattern;
    string base;
public:
    bool isMatch ( string s, string p )
    {
        //fafafaxydeadasfxydtsdaxy
        //.*xy.t.*xy
        base = s;
        parsedPattern = parsePattern ( p );
        return recursionMatch ( 0, 0 );
    }

    bool recursionMatch ( int posStr, int posVec )
    {
        //string a = "bbbba";
        //string p = ".*a*a";
        if ( posStr >= base.size() && posVec >= parsedPattern.size() ) return true;
        if ( posStr >= base.size() && posVec < parsedPattern.size() )
        {
            return allIsStar ( posVec );
        }
        if ( posStr < base.size() && posVec >= parsedPattern.size() ) return false;
        string& pattern = parsedPattern[posVec];
        if ( hasStar ( pattern ) )
        {
            return match ( base[posStr], parsedPattern[posVec] ) && (
                       ( recursionMatch ( posStr + 1, posVec + 1 ) )
                       || ( recursionMatch ( posStr + 1, posVec ) )
                   )
                   ||
                   recursionMatch ( posStr, posVec + 1 ) ;
        }
        else
        {
            return match ( base[posStr], parsedPattern[posVec] ) && ( recursionMatch ( posStr + 1, posVec + 1 ) );
        }
    }

    bool allIsStar ( int pos )
    {
        bool isStar = true;
        for ( int i = pos; i < parsedPattern.size(); i++ )
        {
            isStar &= hasStar ( parsedPattern[i] );
        }
        return isStar;
    }

    static bool match ( char source, const string& pattern )
    {
        return pattern[0] == '.' || pattern[0] == source;
    }

    static bool hasStar ( const string& value )
    {
        return value.size() == 2 && value[1] == '*';
    }

    static vector<string> parsePattern ( const string& p )
    {
        vector<string> parsed;
        int i = 0;
        while ( i < p.size() )
        {
            if ( i + 1 < p.size() )
            {
                if ( p[i + 1] == '*' )
                {
                    parsed.emplace_back ( move ( string{ p[i], p[i + 1] } ) );
                    i = i + 2;
                }
                else
                {
                    parsed.emplace_back ( move ( string{ p[i]} ) );
                    i++;
                }
            }
            else
            {
                parsed.emplace_back ( move ( string{ p[i] } ) );
                i++;
            }
        }
        return parsed;
    }
};

int main()
{
    string a = "fafafaxydeadasfxydtsdaxy";
    string p = ".*xy.t.*xy.*";
    cout << Solution().isMatch ( a, p ) << "\n";
    system ( "pause" );
}



改善

运用动态规划的思想,添加一个变量int dp[256][256];用于存储recursionMatch ( int posStr, int posVec )的状态
可以避免很多次重复计算。时间也从1000ms进步到49ms。

如下

#include <string>
#include <vector>
#include <iostream>

using namespace std;

// . -> char
// .* -> n*char
// x -> x
// x* -> x * n
class Solution
{
private:
    vector<string> parsedPattern;
    string base;
    int dp[256][256];
public:
    bool isMatch ( string s, string p )
    {
        //fafafaxydeadasfxydtsdaxy
        //.*xy.t.*xy
        for (int i = 0; i < 256; i++)
        {
            for (int j = 0; j < 256; j++)
            {
                dp[i][j] = -1;
            }
        }
        base = s;
        parsedPattern = parsePattern ( p );
        return recursionMatch ( 0, 0 );
    }

    bool recursionMatch ( int posStr, int posVec )
    {
        if (dp[posStr][posVec] != -1)
        {
            return dp[posStr][posVec];
        }
        bool ans = false;
        //string a = "bbbba";
        //string p = ".*a*a";
        if ( posStr >= base.size() && posVec >= parsedPattern.size() ) return true;
        if ( posStr >= base.size() && posVec < parsedPattern.size() )
        {
            ans = allIsStar ( posVec );
            dp[posStr][posVec] = ans ? 1 : 0;
            return ans;
        }
        if ( posStr < base.size() && posVec >= parsedPattern.size() ) return false;
        string& pattern = parsedPattern[posVec];
        if ( hasStar ( pattern ) )
        {
            ans = match(base[posStr], parsedPattern[posVec]) && (
                       ( recursionMatch ( posStr + 1, posVec + 1 ) )
                       || ( recursionMatch ( posStr + 1, posVec ) )
                   )
                   ||
                   recursionMatch ( posStr, posVec + 1 ) ;
            dp[posStr][posVec] = ans ? 1 : 0;
            return ans;
        }
        else
        {
            ans = match(base[posStr], parsedPattern[posVec]) && (recursionMatch(posStr + 1, posVec + 1));
            dp[posStr][posVec] = ans ? 1 : 0;
            return ans;
        }
    }

    bool allIsStar ( int pos )
    {
        bool isStar = true;
        for ( int i = pos; i < parsedPattern.size(); i++ )
        {
            isStar &= hasStar ( parsedPattern[i] );
        }
        return isStar;
    }

    static bool match ( char source, const string& pattern )
    {
        return pattern[0] == '.' || pattern[0] == source;
    }

    static bool hasStar ( const string& value )
    {
        return value.size() == 2 && value[1] == '*';
    }

    static vector<string> parsePattern ( const string& p )
    {
        vector<string> parsed;
        int i = 0;
        while ( i < p.size() )
        {
            if ( i + 1 < p.size() )
            {
                if ( p[i + 1] == '*' )
                {
                    parsed.emplace_back ( move ( string{ p[i], p[i + 1] } ) );
                    i = i + 2;
                }
                else
                {
                    parsed.emplace_back ( move ( string{ p[i]} ) );
                    i++;
                }
            }
            else
            {
                parsed.emplace_back ( move ( string{ p[i] } ) );
                i++;
            }
        }
        return parsed;
    }
};

int main()
{
    string a = "fafafaxydeadasfxydtsdaxy";
    string p = ".*xy.t.*xy.*";
    cout << Solution().isMatch ( a, p ) << "\n";
    system ( "pause" );
}



posted @ 2017-11-22 16:50  开学五年级了  阅读(206)  评论(0编辑  收藏  举报