zoukankan      html  css  js  c++  java
  • 字符串正则匹配(递归/DP)

    Wildcard-Matching &  Regular Expression Matching

    Wildcard-Matching中?匹配任意一个字符,*匹配任意长度字符串包括空字符串

    方法一:记录*的位置,分别考虑*匹配空,匹配一个,匹配两个,三个...

     1     bool isMatch(const char *s, const char *p) {
     2         int sStar=-1,pStar=-1;
     3         int i=0,j=0;
     4         for(i=0;i<strlen(s);)//不考虑p字符串长 s=''aa'', p=''a''
     5         {
     6             if(p[j]=='*')
     7             {
     8                 sStar=i;
     9                 pStar=j;
    10                 j++;
    11             }
    12             else if(p[j]==s[i]||p[j]=='?')
    13             {
    14                 i++;
    15                 j++;
    16             }
    17             else if(sStar>=0)//没有匹配但之前记录sStar了
    18             {
    19                 i = ++sStar;
    20                 j = pStar+1;
    21             }
    22             else return false;
    23         }
    24         while(p[j]=='*')j++;
    25         return j==strlen(p);
    26     }

    方法二:DP dp[i][j]=1表示s[0:i)与p[0:j)匹配,状态转移以*划分两种情况,包含*又有两种状态转移,根据无后效性可知,有匹配空和匹配s中的一个字符这两种

     1 bool isMatch(const char *s, const char *p) {
     2         int dp[strlen(s)+1][strlen(p)+1];
     3         memset(dp,0,sizeof(dp));
     4         dp[0][0]=1;
     5         for(int j=1;j<=strlen(p);j++)
     6         {
     7             if(p[j-1]=='*')
     8                 dp[0][j]=dp[0][j-1];
     9         }
    10         for(int i=1;i<=strlen(s);i++)
    11             for(int j=1;j<=strlen(p);j++)
    12             {
    13                 if(p[j-1]=='*')
    14                     dp[i][j]=dp[i][j-1]||dp[i-1][j];
    15                 else
    16                     dp[i][j]=dp[i-1][j-1]&&(s[i-1]==p[j-1]||p[j-1]=='?');
    17             }
    18         return dp[strlen(s)][strlen(p)];
    19     }

     Regular Expression Matching

    *表示*之前的字符可以有0个,1个或是多个

    方法一:递归

    注意不应该先判原串s为空,p为*也可以

    p[1]==* 需要匹配s中的一个字符时,注意p不能去掉首字符,因为*号前面的字符可以有无限个;

    1 bool isMatch(string s, string p)
    2 {
    3     if(p.empty())return s.empty();
    4     if(p.size()>1&&p[1]=='*')
    5         return isMatch(s,p.substr(2))||(!s.empty() && (s[0] == p[0] || p[0] == '.') && isMatch(s.substr(1),p));
    6     else
    7         return !s.empty()&& (p[0]==s[0]||p[0]=='?') && isMatch(s.substr(1),p.substr(1));
    8 }

    方法二:DP  dp[i][j]=1表示s[0:i)与p[0:j)匹配

    1.  P[i][j] = P[i - 1][j - 1], if p[j - 1] != '*' && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
    2.  P[i][j] = P[i][j - 2], if p[j - 1] == '*' and the pattern repeats for 0 times;
    3.  P[i][j] = P[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'), if p[j - 1] == '*' and the pattern repeats for at least 1 

     1 bool isMatch(string s, string p) {
     2     int m = s.size(), n = p.size();
     3     int dp[m+1][n+1];
     4     memset(dp,0,sizeof(dp));
     5     dp[0][0] = 1;
     6     for (int i = 0; i <= m; ++i) {
     7         for (int j = 1; j <= n; ++j) {
     8             if (j > 1 && p[j - 1] == '*') {
     9                 dp[i][j] = dp[i][j - 2] || (i > 0 && (s[i - 1] == p[j - 2] || p[j - 2] == '.') && dp[i - 1][j]);
    10             } else {
    11                 dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
    12             }
    13         }
    14     }
    15     return dp[m][n];
    16 }

    参考自:Grandyang

  • 相关阅读:
    CMSIS_OS中osMailPut 和 osMessagePut 的问题
    网络:W5500抓包TCP segment of a reassembled PDU
    网络:W5500 UDP数据包格式注意事项
    笔记:把编译时间加入到目标文件
    笔记:git和码云
    笔记:git基本操作
    FreeRtos堆栈检测应用
    一个由自增运算符以及C语法顺序细节引起的bug
    高级文件操作
    linux 权限相关
  • 原文地址:https://www.cnblogs.com/demian/p/10498659.html
Copyright © 2011-2022 走看看