通配符匹配字符串 Wildcard Matching
来源:互联网 发布:火箭队 机械 知乎 编辑:程序博客网 时间:2024/04/29 22:19
问题:实现支持?和*两个通配符的字符串匹配函数。
Implement wildcard pattern matching with support for '?'
and '*'
.
'?' Matches any single character.'*' Matches any sequence of characters (including the empty sequence).The matching should cover the entire input string (not partial).The function prototype should be:bool isMatch(const char *s, const char *p)Some examples:isMatch("aa","a") → falseisMatch("aa","aa") → trueisMatch("aaa","aa") → falseisMatch("aa", "*") → trueisMatch("aa", "a*") → trueisMatch("ab", "?*") → trueisMatch("aab", "c*a*b") → false
回忆一下类似的一个问题《简单的正则表达式匹配 Regular Expression Matching》,注意其中的区别:两个问题中*所具备的匹配能力是不同的。
思路一:递归求解。虽然已经把重复出现的*过滤,不过超时了。
class Solution {public: bool isMatch(const char *s, const char *p) { if(s == NULL || p == NULL) return false; return isValid(s, p); } bool isValid(const char *s, const char *p) { if(*p == '\0') return *s == '\0'; if(*p == '?') return isValid(s+1, p+1); else if(*p != '*') { if(*p == *s) return isValid(s+1, p+1); else return false; } else { p++; while(*p == '*') p++; while(*s != '\0') { if(isValid(s, p)) return true; s++; } return isValid(s, p); } }};思路二:动态规划法。
设置状态量H[pn+1][sn+1]。H[i][j]表示p的前i个字符能否匹配成功s的前j个字符。
递推关系:如果H[i-1][j-1]=1,若p[i]='?'或者p[i]==s[j],那么H[i][j]为1;若p[i]='*',那么H[i][j-1]到H[i][sn]都为1。
初始条件:H[0][0]=1。
注意:必须要提前把不可能匹配的情况排除,否则会超时。当p串中非*字符的个数大于0且少于s串的字符个数时,匹配不可能成功。
class Solution {public: bool isMatch(const char *s, const char *p) { if(s == NULL || p == NULL) return false; //计数:记录p串的字符个数(pn)、s串的字符个数(sn)、p串中*的个数(stars) const char *p1; p1 = p; int stars = 0; while(*p1 != 0) { if(*p1 == '*') stars++; p1++; } int pn = p1 - p; p1 = s; while(*p1 != 0) p1++; int sn = p1 - s; if(pn == stars && stars > 0) //若p串中只有*,一定匹配 return true; if(pn - stars > sn) //若p串中非*字符的个数多于s串,不可能匹配 return false; int H[pn+1][sn+1]; memset(H,0 ,sizeof(H)); H[0][0] = 1; for(int i=1;i<=pn;i++) { if(p[i-1] != '*') break; H[i][0] = 1; } for(int i=1;i<=pn;i++) { for(int j=1;j<=sn;j++) { if(H[i-1][j-1] == 1) { if(p[i-1] == '?' || p[i-1] == s[j-1]) { H[i][j] = 1; } else if(p[i-1] == '*') { for(int k=j-1;k<=sn;k++) H[i][k] = 1; } } } } //当p串以*结尾时,与s的匹配有可能提前结束。 int last; for(last=pn;last>=0;last--) if(H[last][sn] == 1) break; last++; while(last<=pn && p[last-1] == '*') last++; if(last == pn+1) return true; return H[pn][sn] == 1; }};
思路二的优化:上面的动态规划中对'*'星号的递推处理不太恰当,使得DP之后还要再处理一下。现在改进一下DP的递推方法:
在DP的二重循环遍历到H[i][j](即判断p串的前i项是否匹配s串的前j项)时,
如果有p[i]='?'或者p[i]==s[j] ,并且,H[i-1][j-1]=1,那么H[i][j]为1。
如果有p[i]='*',并且,H[i-1][j]=1 ,那么H[i][j]~H[i][sn]都为1。
另外初始情况时,要把*的情况考虑。
class Solution {public: bool isMatch(const char *s, const char *p) { if(s == NULL || p == NULL) return false; //计数:记录p串的字符个数(pn)、s串的字符个数(sn)、p串中*的个数(stars) const char *p1; p1 = p; int stars = 0; while(*p1 != 0) { if(*p1 == '*') stars++; p1++; } int pn = p1 - p; p1 = s; while(*p1 != 0) p1++; int sn = p1 - s; if(pn == stars && stars > 0) //若p串中只有*,一定匹配 return true; if(pn - stars > sn) //若p串中非*字符的个数多于s串,不可能匹配 return false; int H[pn+1][sn+1]; memset(H,0 ,sizeof(H)); H[0][0] = 1; for(int i=1;i<=pn;i++) { if(p[i-1] != '*') break;for(int j=0;j<=sn;j++) //当p串开头就有*H[i][j] = 1; } for(int j=1;j<=sn;j++) { for(int i=1;i<=pn;i++) {if ((H[i-1][j-1] == 1) && (p[i-1] == '?' || p[i-1] == s[j-1])) { H[i][j] = 1; } else if(H[i-1][j] == 1 && p[i-1] == '*') { for(int k=j;k<=sn;k++) H[i][k] = 1; } } } return H[pn][sn] == 1; }};
思路三:在网上看到的优化方法。记录前一个*字符的位置,优先进行单字符匹配,当失败的时候再回来进行通配。
class Solution {public:bool isMatch(const char *s, const char *p) { if(!s && !p) return true; const char *star_p=NULL,*star_s=NULL; while(*s) { if(*p == '?' || *p == *s) { ++p,++s; }else if(*p == '*') { //skip all continuous '*' while(*p == '*') ++p; if(!*p) return true; //if end with '*', its match. star_p = p; //store '*' pos for string and pattern star_s = s; }else if((!*p || *p != *s) && star_p) { s = ++star_s; //skip non-match char of string, regard it matched in '*' p = star_p; //pattern backtrace to later char of '*' }else return false; } //check if later part of p are all '*' while(*p) if(*p++ != '*') return false; return true;}};
0 0
- 通配符匹配字符串 Wildcard Matching
- Wildcard Matching 通配符匹配
- Wildcard Matching 通配符匹配
- Wildcard Matching 通配符匹配
- Wildcard Matching:通配符匹配
- LeetCode: Wildcard Matching (通配符匹配)
- [leetcode] Wildcard Matching 通配符匹配
- [Lintcode]Wildcard Matching 通配符匹配
- [LeeCode]—Wildcard Matching 通配符匹配问题
- [LeetCode]Wildcard Matching 通配符匹配(贪心)
- leetcode-44 Wildcard Matching 通配符匹配
- 44. Wildcard Matching(通配符匹配)
- Wildcard Matching 字符串含?,*匹配
- Leetcode Wildcard Matching 字符串*?模式匹配
- Wildcard Matching 包含? * 的字符串匹配问题
- LeetCode OJ 之 Wildcard Matching(通配符匹配)
- leetCode 44.Wildcard Matching (通配符匹配) 解题思路和方法
- Leetcode #44. Wildcard Matching 通配符匹配 解题报告
- A. Slightly Decreasing Permutations
- ofbiz本地化设置及币种设置
- 开源html3D/2D游戏引擎 Turbulenz USER GUIDE
- C风格读取文件
- 黑马程序员_JAVA基础加强
- 通配符匹配字符串 Wildcard Matching
- jdk与jre的区别
- oracle的各种索引总结
- 黑马程序员_IO流加强
- cmd to disassembling
- 人生第一次面试的感想
- 在遇到xcode 左边class栏末尾标记
- 数据结构之链表
- test hello