leetcode 10.正则表达式

若如初见. 提交于 2020-04-04 18:04:16

题目描述特别简洁:

 

 

 先贴代码:

class Solution {
    public :
        bool isMatch(string s ,string p){
            int dp[100][100] = {0};                        
            s.insert(0,1,'@');p.insert(0,1,'@');           //为了将空字符考虑在内,初始化插入@方便之后的操作
            int ls = s.size(),lp = p.size();
            dp[0][0] = 1;                                  //初始化dp(p与s为空字符)
            for(int j = 1 ; j < lp; j++){
                for(int i = 0; i < ls; i ++){
                    if(i != 0 && (s[i] == p[j] || p[j] == '.') && dp[i-1][j-1] == 1 ){     //直接匹配
                        dp[i][j] = 1;
                    }
                    else if(p[j] == '*')                                                   //当p[j]为*时情况较为复杂
                    {
                        if(j - 2 >= 0 && dp[i][j - 2] == 1)                                //可以直接把零个随意字符通配Σ*忽略
                        {
                            dp[i][j] = 1;
                        }
                        else if(i !=  0 && (dp[i - 1][j]  == 1 || dp[i - 1][j - 1] == 1) && (s[i] == p[j - 1] || p[j-1] == '.'))       //将Σ*于n个Σ匹配
                        {
                            dp[i][j] = 1;
                        }
                    }
                }
            }
    //        for(int i = 0;i < lp; i++)                        //把dp打印出来用于debug
    //        {
    //            for(int j = 0;j < ls; j++)
    //            {
    //                cout << dp[j][i];
    //            }
    //            cout<<endl;
    //        }
            if(dp[ls - 1][lp - 1])
            {
                cout << "ture";
                return 1;
            }
            else{
                cout << "false";
                return 0;
            }
        }
}; 

 

通过如下的样例说明状态转移的过程(本题难就难在状态转移的方式比较多样,这也导致用简单的递归方法解题非常困难):

Case #1:

aaa

a*a

(如果将三个a直接用a*通配掉了那就直接得到了一个false)

Solution #1:

ture

DP(dpij) #1: 

(当s.substr(0,i)与p.substr(0,j)能够相互匹配时dpij = 1)

1 0 0 0      (空字符串)
0 1 0 0      (dpi-1  j-1 == 1 时 s[i] 与 p[j] 是等价的 就有 dpij = 1)
1 1 1 1      (p[j] == '*' 且 dpi  j-2 == 1 这表明 考虑dpij的时候 ‘*’ 与它之前的 ‘Σ’ 可以视作 0 个Σ 于是 两个子字符串匹配 dpij = 1) (p[j] == '*' 且 dpi-1  j == 1 且 s[i] 与 p[j-1]  (也就是Σ)能够匹配 则 dpij = 1)
0 1 1 1      (继续进行上面的状态转移,得到答案) 

Case #2:

abp

.*t

Solution #2:

false

(虽然.*匹配任意字符串但是加上个t就不行了)

DP(dpij) #2:

1 0 0 0
0 1 0 0
1 1 1 1
0 0 0 0

 

Case #3:

bbbopctf

b*.*ctf

(若只想到用.*匹配后面所有的字符便无法匹配“ctf”)

Solution #3:

ture

DP(dpij) #3:

1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0
0 1 1 1 1 0 0 0 0
1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1

 

 

动态规划编写简单,优势明显。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!