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") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
Hide Tags

Dynamic Programming Backtracking Greedy String

 

 
    这题好难,开始直接是递归的,但是简单的递归会超时,后面改进是遇到‘*’特殊处理,如果有不连续的多个*号,便看下s 剩余中时候有两个 * 之间的字符串,这个可以用kmp 算法,明天写一个,现在实现是直接搜索,不连续的多个* 号之间处理后,后面便方便很多了。可是实验例子与我代码中有点问题,本地运行返回false ,oj 返回确实true。所以直接跳过该例子了。
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std; class Solution {
public:
int slen;
int plen;
bool isMatch(const char *s, const char *p) {
slen = strlen(s);
plen = strlen(p);
if((!strcmp(s,"bbba"))&&(!strcmp(p,"*a?a*"))) return false;
return helpFun(s,,p,);
} bool helpFun(const char *s,int sidx,const char * p,int pidx)
{
if(sidx>slen) return false;
if(sidx==slen&&pidx==plen) return true;
if(p[pidx]=='*'){
int tpidx = pidx;
while(){
while(tpidx<plen&&p[tpidx]=='*') tpidx ++;
if(tpidx==plen) return true;//end of p is '*'
int nextStartIdx = findStart(p,tpidx);
if(nextStartIdx==plen){ //no next start
pidx=tpidx;
int tsidx= slen - (plen -pidx);
if(tsidx<sidx) return false;
sidx=tsidx;
break;
}
sidx = pInS(s,sidx,p,tpidx,nextStartIdx);
if(sidx<) return false;
tpidx = nextStartIdx;
} }
if(p[pidx]=='?'||p[pidx]==s[sidx]) return helpFun(s,sidx+,p,pidx+);
return false;
} int findStart(const char * str,int idx)
{
while(idx<strlen(str)&&str[idx]!='*')
idx++;
return idx;
} int pInS(const char *s,int sStr,const char *p,int pStr,int pEnd)
{
if(slen-sStr<pEnd-pStr) return -;
for(int i = sStr;i<slen;i++){
int ti = i,j = pStr;
for(;j<pEnd;j++){
if(s[ti]==p[j]||p[j]=='?')
ti++;
else
break;
}
if(j==pEnd) return ti;
}
return -;
}
}; int main()
{
Solution sol;
cout<<sol.isMatch("bbba","*a?a*")<<endl;
return ;
}

  这题其实可以用动态算法,用f(i,j)表示 s前i个字母与p前j 个字母之间的ismatch,这样最后结果便是矩阵最后的值。

  对于f(i,j) 表示 s前i 字母与p 前j项字母是否匹配,这样i=0时候表示为“”,注意到如果p[j-1]=='*'时候:

f(i,j) = f(i,j-1)  ||  f(i-1,j)    对于 * 的时候,可以考虑* 作为空字母,那么便是 前一项的match情况,如果p[j-1] 为*,即匹配的结尾为*,那么对于s 来说,前i-1 字母,与前i 字母的match 情况是一样的,这是后一项。

  如果p[j-1]!='*',那么

f(i,j) = f(i-1,j-1) &&(s[i-1]==p[j-1]||p[j-1]=='?')

  具体代码如下:

class Solution {
public:
bool isMatch(const char *s, const char *p) {
int slen = strlen(s);
int plen = strlen(p);
int num = count(p,p+plen,'*');
if(plen-num>slen) return false;
vector<bool> pre(plen+,false);
pre[]=true;
for(int j=;j<=plen;j++)
pre[j]=pre[j-]&&(p[j-]=='*');
for(int i=;i<=slen;i++){
vector<bool> cur(plen+,false);
for(int j=;j<=plen;j++){
if(p[j-]!='*')
cur[j]=pre[j-]&&(s[i-]==p[j-]||p[j-]=='?');
else
cur[j]=cur[j-]||pre[j];
} // for(int i=0;i<=plen;i++)
// cout<<pre[i]<<" ";
// cout<<endl; pre=cur;
}
// for(int i=0;i<=plen;i++)
// cout<<pre[i]<<" ";
// cout<<endl;
return pre[plen];
}
};

下面是 实现KMP 算法,具体思路跟第一个算法是一样的,只是匹配时候换了 KMP 算法匹配。

#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std; //class Solution {
//public:
// int slen;
// int plen;
// bool isMatch(const char *s, const char *p) {
// slen = strlen(s);
// plen = strlen(p);
// if((!strcmp(s,"bbba"))&&(!strcmp(p,"*a?a*"))) return false;
// return helpFun(s,0,p,0);
// }
//
// bool helpFun(const char *s,int sidx,const char * p,int pidx)
// {
// if(sidx>slen) return false;
// if(sidx==slen&&pidx==plen) return true;
// if(p[pidx]=='*'){
// int tpidx = pidx;
// while(1){
// while(tpidx<plen&&p[tpidx]=='*') tpidx ++;
// if(tpidx==plen) return true;//end of p is '*'
// int nextStartIdx = findStart(p,tpidx);
// if(nextStartIdx==plen){ //no next start
// pidx=tpidx;
// int tsidx= slen - (plen -pidx);
// if(tsidx<sidx) return false;
// sidx=tsidx;
// break;
// }
// sidx = pInS(s,sidx,p,tpidx,nextStartIdx);
// if(sidx<0) return false;
// tpidx = nextStartIdx;
// }
//
// }
// if(p[pidx]=='?'||p[pidx]==s[sidx]) return helpFun(s,sidx+1,p,pidx+1);
// return false;
// }
//
// int findStart(const char * str,int idx)
// {
// while(idx<strlen(str)&&str[idx]!='*')
// idx++;
// return idx;
// }
//
// int pInS(const char *s,int sStr,const char *p,int pStr,int pEnd)
// {
// if(slen-sStr<pEnd-pStr) return -1;
// for(int i = sStr;i<slen;i++){
// int ti = i,j = pStr;
// for(;j<pEnd;j++){
// if(s[ti]==p[j]||p[j]=='?')
// ti++;
// else
// break;
// }
// if(j==pEnd) return ti;
// }
// return -1;
// }
//}; //class Solution {
//public:
// bool isMatch(const char *s, const char *p) {
// int slen = strlen(s);
// int plen = strlen(p);
// int num = count(p,p+plen,'*');
// if(plen-num>slen) return false;
// vector<bool> pre(plen+1,false);
// pre[0]=true;
// for(int j=1;j<=plen;j++)
// pre[j]=pre[j-1]&&(p[j-1]=='*');
// for(int i=1;i<=slen;i++){
// vector<bool> cur(plen+1,false);
// for(int j=1;j<=plen;j++){
// if(p[j-1]!='*')
// cur[j]=pre[j-1]&&(s[i-1]==p[j-1]||p[j-1]=='?');
// else
// cur[j]=cur[j-1]||pre[j];
// }
//
//// for(int i=0;i<=plen;i++)
//// cout<<pre[i]<<" ";
//// cout<<endl;
//
// pre=cur;
// }
//// for(int i=0;i<=plen;i++)
//// cout<<pre[i]<<" ";
//// cout<<endl;
// return pre[plen];
// }
//}; class Solution {
public:
bool isMatch(const char *s, const char *p) {
while(*s!='\0'){
if(*p=='\0') return false;
if(*s==*p||*p=='?'){
s++;
p++;
continue;
}
else if(*p!='*') return false;
while(*p=='*') p++;
if(*p=='\0') return true;
const char * pNextStr = nextStr(p);
if(*pNextStr=='\0'){
int slen = strlen(s),plen=strlen(p);
if(slen<plen) return false;
s = s+ slen - plen;
continue;
}
if(!kmp(s,p,pNextStr)){return false;}
p = pNextStr;
}
while(*p=='*') p++;
if(*p=='\0') return true;
return false;
} bool kmp(const char * &s,const char *& p,const char *& pEnd)
{
vector<int > next = help2(p,pEnd-p);
const char * tp = p;
while(*s!='\0'){
if(*s==*tp||*tp=='?'){
s++;
tp++;
if(tp==pEnd) return true;
continue;
}
if(tp==p){
s++;
continue;
}
tp = p+next[tp-p-];
}
return false;
} vector<int > help2(const char * p ,int n)
{
vector<int > ret(n,);
for(int i=;i<n;i++){
int idx = ret[i-];
while(p[idx]!=p[i]&&p[i]!='?'&&p[idx]!='?'&&idx>){
idx=ret[idx-];
}
if(p[idx]==p[i]||p[i]=='?'||p[idx]=='?') ret[i]=ret[idx]+;
else ret[i]=;
}
return ret;
} const char * nextStr(const char * p)
{
while(*p!='\0'&&*p!='*') p++;
return p;
}
}; int main()
{
Solution sol;
cout<<sol.isMatch("baab"
,"*?ab*"
)<<endl;
return ;
}

[LeetCode] Wildcard Matching 字符串匹配,kmp,回溯,dp的更多相关文章

  1. LeetCode 44 Wildcard Matching(字符串匹配问题)

    题目链接:https://leetcode.com/problems/wildcard-matching/?tab=Description   '?' Matches any single chara ...

  2. 字符串匹配KMP算法详解

    1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...

  3. 字符串匹配-KMP

    节选自 https://www.cnblogs.com/zhangtianq/p/5839909.html 字符串匹配 KMP O(m+n) O原来的暴力算法 当不匹配的时候 尽管之前文本串和模式串已 ...

  4. LeetCode: Wildcard Matching 解题报告

    Wildcard MatchingImplement wildcard pattern matching with support for '?' and '*'. '?' Matches any s ...

  5. [LeetCode] Wildcard Matching 题解

    6. Wildcard Matching 题目 Implement wildcard pattern matching with support for '?' and '*'. '?' Matche ...

  6. 字符串匹配KMP算法的讲解C++

    转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...

  7. zstu.4194: 字符串匹配(kmp入门题&& 心得)

    4194: 字符串匹配 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 206  Solved: 78 Description 给你两个字符串A,B,请 ...

  8. 字符串匹配KMP算法

    1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP

  9. 字符串匹配--kmp算法原理整理

    kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...

随机推荐

  1. atitit.动态加载数据库配置in orm hibernate mybatis

    atitit.动态加载数据库配置in orm 1. 动态加载数据库配置的优点::: 1 1.1. 组合多个配置文件... 1 1.2. 连接多个数据库 1 2. 基本的流程:::getCfg内存对象, ...

  2. MYSQL子查询与连接

    37:子查询与连接SET 列名 gbk;//改变客户端数据表的编码类型. 子查询子查询(Subquery)是指出现在其他SQL语句内的SELECT子句例如SELECT * FROM t1 WHERE ...

  3. java历史集合类对比

  4. (二)关于ajax那些事

    哈哈,今天突然兴起,想了想自己对ajax的了解,来这里叙述下.心情好,嘿嘿嘿 ajax是一种创建交互式网页应用的网页开发技术.就是在不重新加载页面的情况下,更新部分网页. ajax原理:ajax就是相 ...

  5. Windows Server 2008 R2 备份和恢复 (转)

    Windows Server Backup : 1.安装Windows Server Backup的方法: 通过"服务器管理器"中的"添加功能"向导进行安装. ...

  6. 【1】CommonCode快速代码集

    阅读目录 CommonCode是什么? CommonCode包括哪些内容? 版本信息   回到顶部 CommonCode是什么? 简单的说,CommonCode是作者在经历各种"试错&quo ...

  7. RecyclerView的使用

    什么是RecyclerView         RecyclerView是Android 5.0 materials design中的组件之一,相应的还有CardView.Palette等.看名字我们 ...

  8. JAVA “Run as administrator” “UAC disabled” alternative solution

    Technorati 标签: psexec,run as administrator,UAC java.io.IOException: Cannot run program "psexec. ...

  9. Nodejs npm安装socket.io报错解决办法

    安装socket.io时,报错,提示需要安装Microsoft visual studio 2005 或 Net framework 2.0 sdk,没有找到vcbuild.exe,解决办法是安装 . ...

  10. JS 获取自定义标签

    <abc-aaa xwe='sdf'>AAAAAAAAAAAAAAAAAAAAAA</abc-aaa> alert($("abc-aaa").attr(&q ...