https://leetcode.com/problems/wildcard-matching/
方法一:DFS (需要开数组判重)
这里我得承认,作弊了点,,因为有一组数据,长度4100左右两个字符串匹配。 所以开数组大小其实是WA了一次 然后才确定大小的,,,,想想为什么需要判重:
s=aaaaa
p=a**a
dfs(s-2,p-2)可能通过多种途径到达,这样的话每种途径都Dfs一次后面的,会TLE
#include <cstdio> #include <iostream> #include <vector> #include <algorithm> #include <map> #include <set> using namespace std; const int SIZE = 4100+1; char vis[SIZE][SIZE]; class Solution { public: bool isMatch(string s, string p) { int ptrs = 0, ptrp = 0; for(int i=0;i<s.size();i++) for(int j=0;j<p.size();j++) { vis[i][j] = -1; } return match(s,p, ptrs, ptrp); } bool judge(string p, int ptrp) { int flag = 1; for(int i=ptrp;i<p.size();i++) if( p[i] != '*' ) { flag = 0; break; } return flag; } bool match(string s, string p, int ptrs, int ptrp) { if(ptrs >= s.size()) { if(ptrp>=p.size() || judge(p, ptrp) ) return true; else return false; } if(ptrp >= p.size()) return false; if(p[ptrp] == s[ptrs] || p[ptrp] == '?') { while(ptrp<p.size() && ptrs<s.size() && (p[ptrp] == s[ptrs] || p[ptrp] == '?')){ ptrs++, ptrp++; } return match(s, p, ptrs, ptrp); } else { if(p[ptrp] == '*') { return matchStar(s, p, ptrs, ptrp); } else { return false; } } } bool matchStar(string s, string p, int ptrs, int ptrp) { int flag = 0; while(ptrs<s.size() ) { if( vis[ptrs][ptrp]==-1 ) { vis[ptrs][ptrp] = match(s,p,ptrs, ptrp+1); // 相当于枚举匹配的个数,从0个开始 } if(vis[ptrs][ptrp] == 1) return true; ptrs++; } return match(s,p,ptrs, ptrp+1); } }; int main() { freopen("44.txt", "r", stdin); string s,p; while( cin >> s >> p ) { Solution ss; cout << ss.isMatch(s, p) << endl; } return 0; }
这个代码好巧妙 ,,, 还有点不是很理解
class Solution { public: bool isMatch(string s , string p) { return Match(s.c_str(), p.c_str()); } bool Match(const char *s, const char *p) { const char *ss = s, *pp = NULL; while('\0' != *s) { if('?' == *p || *s == *p) ++ s, ++ p; else if('*' == *p) ss = s, pp = p ++; else if(pp != NULL) //pp相当于*的位置,也就是当不符合匹配的情况,如果是*可以继续s++ s = ++ ss, p = pp + 1; else return false; } while('*' == *p) ++ p; return '\0' == *p; } };
当然,这种题,还可以用动态规划的思路处理。用bool型二维数组vvb[i][j]表示s的前i个字符和p的前j个字符是否匹配。
初始值,vvb[0][0]为true,vvb[0][j]的值取决于p前一个位置是否为‘*’以及前一情况是否匹配。
当p[j]等于‘?’或者s[i]等于p[j]时,则vvb[i][j]的值取决于vvb[i-1][j-1],即为s的前一位置和p的前一位置是否匹配;
当p[j]等于‘*’时,如果该‘*’可以匹配s中的0个或者1个字符,分别对应vvb[i][j-1],即s的当前位置和p的前一位置是否匹配,以及vvb[i-1][j-1],即s的前一位置和p的前一位置是否匹配。
可惜MLE,看了数据量不小啊。。。
时间复杂度:O(ls*lp)(ls和lp分别为s和p字符串的长度)
空间复杂度:O(ls*lp)
1 class Solution
2 {
3 public:
4 bool isMatch(const char *s, const char *p)
5 {
6 int ls = strlen(s), lp = strlen(p);
7 vector<vector<bool> > vvb(ls + 1, vector<bool>(lp + 1, false));
8 vvb[0][0] = true;
9
10 for(int j = 1; j <= lp; ++ j)
11 {
12 vvb[0][j] = vvb[0][j - 1] && '*' == p[j - 1];
13 for(int i = 1; i <= ls; ++ i)
14 {
15 if('?' == p[j - 1] || s[i - 1] == p[j - 1])
16 vvb[i][j] = vvb[i - 1][j - 1];
17 else if('*' == p[j - 1])
18 vvb[i][j] = vvb[i][j - 1] || vvb[i - 1][j - 1];
19 }
20 }
21
22 return vvb[ls][lp];
23 }
24 };
由于判断当前能否匹配的时候,只是用到了前一情况的结果,因此可以申请一维数组vb[i],表示s的前i个字符和p的前j个字符是否匹配。
当p[j]不是‘*’的时候,只要判断如果当前s[i-1]和p[j-1]上的字符是否匹配,并且vb[i-1]是否为true; 这里可以考虑从后往前遍历s,这样vb[i-1]就是前一情况。
当p[j]是‘*’的时候,因为‘*’可以匹配任意字符串,所以在前面的vb[i]只要有true,那么剩下i后面就都是true了。
还是TLE,因为最后一组数据过不了,好多童鞋选择跳过这组数据了。。。
时间复杂度:O(ls*lp)(ls和lp分别为s和p字符串的长度)
空间复杂度:O(ls*lp)
1 class Solution
2 {
3 public:
4 bool isMatch(const char *s, const char *p)
5 {
6 int ls = strlen(s), lp = strlen(p);
7
8 vector<bool> vb(ls + 1, false);
9 vb[0] = true;
10
11 for(int j = 1; j <= lp; ++ j)
12 {
13 if('*' != p[j - 1])
14 for(int i = ls; i > 0; -- i)
15 vb[i] = vb[i - 1] && ('?' == p[j - 1] || s[i - 1] == p[j - 1]);
16 else
17 {
18 int i;
19 for(i = 0; i <= ls && !vb[i]; ++ i);
20 for( ; i <= ls; ++ i)
21 vb[i] = true;
22 }
23 vb[0] = vb[0] && '*' == p[j - 1];
24 }
25
26 return vb[ls];
27 }
28 };
未完待续。。。
时间复杂度:O()
空间复杂度:O()