java字符串匹配dp_字符串正则匹配(递归/DP)

本文介绍两种常见的字符串匹配问题:通配符匹配与正则表达式匹配,并提供两种解决方法——状态记录法与动态规划法。通配符匹配中,?匹配任意一个字符,*匹配任意长度的字符串。正则表达式匹配中,*表示前一个字符可出现0次或多次。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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 returndp[strlen(s)][strlen(p)];19 }

Regular Expression Matching

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

方法一:递归

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

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

1 bool isMatch(string s, stringp)2 {3 if(p.empty())returns.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, stringp) {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 returndp[m][n];16 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值