#include <unordered_map>
#include <iostream>
#include <vector>
using namespace std;
void cleanup(const char*s, const char*p, vector<char> &str, vector<char> &pat){
while (*s) str.push_back(*(s++));
while (*p) {
if (*p != '*') pat.push_back(*(p++));
else {
if (!pat.size() || pat.back() != '*') pat.push_back(*(p++));
else ++p;
}
}
}
bool helper(int state, int offset, int strptr, int patptr, \
vector<char> &str, vector<char> &pat, \
unordered_multimap<int, int> &failoffset) {
// DP part
auto range = failoffset.equal_range(state);
for (auto it = range.first; it != range.second; it++)
if (it->second == offset) return false;
int thisoffset;
for (thisoffset = 0; thisoffset <= str.size() - strptr; thisoffset++) {
int tmpstrptr = strptr + thisoffset;
int tmppatptr = patptr + 1;
while (tmppatptr != pat.size() && tmpstrptr != str.size() && \
pat[tmppatptr] != '*' && \
(str[tmpstrptr] == pat[tmppatptr] || pat[tmppatptr] == '?')) {
tmppatptr++; tmpstrptr++;
}
if (tmppatptr == pat.size() && tmpstrptr == str.size()) return true;
else if (tmppatptr == pat.size()) {
failoffset.insert(make_pair(state, offset + thisoffset));
}
else if (tmpstrptr == str.size()) {
while (pat[tmppatptr] == '*' && tmppatptr < pat.size()) tmppatptr++;
if (tmppatptr == pat.size()) return true;
return false;
}
else if (pat[tmppatptr] != '*' && pat[tmppatptr] != str[tmpstrptr]) {
failoffset.insert(make_pair(state, offset + thisoffset));
}
else if (pat[tmppatptr] == '*') {
if (helper(state + 1, offset + thisoffset, tmpstrptr, tmppatptr, str, pat, failoffset))
return true;
failoffset.insert(make_pair(state, offset + thisoffset));
}
}
failoffset.insert(make_pair(state, offset + thisoffset));
return false;
}
bool isMatch(const char*s, const char*p) {
vector<char> str, pat;
unordered_multimap<int, int> um;
cleanup(s, p, str, pat);
int i = 0;
int j = 0;
while (i < str.size() && j < pat.size()) {
if (str[i] == pat[j] || pat[j] == '?') {
i++; j++;
continue;
}
if (pat[j] == '*') break;
return false;
}
if (i == str.size()) {
while (j < pat.size() && pat[j] == '*') j++;
if (j == pat.size()) return true;
return false;
}
if (j == pat.size()) return false;
str.erase(str.begin(), str.begin() + i);
pat.erase(pat.begin(), pat.begin() + j);
return helper(0, 0, 0, 0, str, pat, um);
}
int main() {
//char str[] = "abcdefg";
//char pat[] = "ab*e*f*g*";
char str2[] = "a";
char pat2[] = "a*";
cout << isMatch(str2, pat2);
return 0;
}
I2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHZlY3Rvcj4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnZvaWQgY2xlYW51cChjb25zdCBjaGFyKnMsIGNvbnN0IGNoYXIqcCwgdmVjdG9yPGNoYXI+ICZzdHIsIHZlY3RvcjxjaGFyPiAmcGF0KXsKCXdoaWxlICgqcykgc3RyLnB1c2hfYmFjaygqKHMrKykpOwoJd2hpbGUgKCpwKSB7CgkJaWYgKCpwICE9ICcqJykgcGF0LnB1c2hfYmFjaygqKHArKykpOwoJCWVsc2UgewoJCQlpZiAoIXBhdC5zaXplKCkgfHwgcGF0LmJhY2soKSAhPSAnKicpIHBhdC5wdXNoX2JhY2soKihwKyspKTsKCQkJZWxzZSArK3A7CgkJfQoJfQp9Cgpib29sIGhlbHBlcihpbnQgc3RhdGUsIGludCBvZmZzZXQsIGludCBzdHJwdHIsIGludCBwYXRwdHIsIFwKCQkJdmVjdG9yPGNoYXI+ICZzdHIsIHZlY3RvcjxjaGFyPiAmcGF0LCBcCgkJCXVub3JkZXJlZF9tdWx0aW1hcDxpbnQsIGludD4gJmZhaWxvZmZzZXQpIHsKCS8vIERQIHBhcnQKCWF1dG8gcmFuZ2UgPSBmYWlsb2Zmc2V0LmVxdWFsX3JhbmdlKHN0YXRlKTsKCWZvciAoYXV0byBpdCA9IHJhbmdlLmZpcnN0OyBpdCAhPSByYW5nZS5zZWNvbmQ7IGl0KyspCgkJaWYgKGl0LT5zZWNvbmQgPT0gb2Zmc2V0KSByZXR1cm4gZmFsc2U7CgoJaW50IHRoaXNvZmZzZXQ7Cglmb3IgKHRoaXNvZmZzZXQgPSAwOyB0aGlzb2Zmc2V0IDw9IHN0ci5zaXplKCkgLSBzdHJwdHI7IHRoaXNvZmZzZXQrKykgewoJCWludCB0bXBzdHJwdHIgPSBzdHJwdHIgKyB0aGlzb2Zmc2V0OwoJCWludCB0bXBwYXRwdHIgPSBwYXRwdHIgKyAxOwoJCXdoaWxlICh0bXBwYXRwdHIgIT0gcGF0LnNpemUoKSAmJiB0bXBzdHJwdHIgIT0gc3RyLnNpemUoKSAmJiBcCgkJCXBhdFt0bXBwYXRwdHJdICE9ICcqJyAmJiBcCgkJCShzdHJbdG1wc3RycHRyXSA9PSBwYXRbdG1wcGF0cHRyXSB8fCBwYXRbdG1wcGF0cHRyXSA9PSAnPycpKSB7CgkJCXRtcHBhdHB0cisrOyB0bXBzdHJwdHIrKzsKCQl9CgkJaWYgKHRtcHBhdHB0ciA9PSBwYXQuc2l6ZSgpICYmIHRtcHN0cnB0ciA9PSBzdHIuc2l6ZSgpKSByZXR1cm4gdHJ1ZTsKCQllbHNlIGlmICh0bXBwYXRwdHIgPT0gcGF0LnNpemUoKSkgewoJCQlmYWlsb2Zmc2V0Lmluc2VydChtYWtlX3BhaXIoc3RhdGUsIG9mZnNldCArIHRoaXNvZmZzZXQpKTsKCQl9CgkJZWxzZSBpZiAodG1wc3RycHRyID09IHN0ci5zaXplKCkpIHsKCQkJd2hpbGUgKHBhdFt0bXBwYXRwdHJdID09ICcqJyAmJiB0bXBwYXRwdHIgPCBwYXQuc2l6ZSgpKSB0bXBwYXRwdHIrKzsKCQkJaWYgKHRtcHBhdHB0ciA9PSBwYXQuc2l6ZSgpKSByZXR1cm4gdHJ1ZTsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQllbHNlIGlmIChwYXRbdG1wcGF0cHRyXSAhPSAnKicgJiYgcGF0W3RtcHBhdHB0cl0gIT0gc3RyW3RtcHN0cnB0cl0pIHsKCQkJZmFpbG9mZnNldC5pbnNlcnQobWFrZV9wYWlyKHN0YXRlLCBvZmZzZXQgKyB0aGlzb2Zmc2V0KSk7CgkJfQoJCWVsc2UgaWYgKHBhdFt0bXBwYXRwdHJdID09ICcqJykgewoJCQlpZiAoaGVscGVyKHN0YXRlICsgMSwgb2Zmc2V0ICsgdGhpc29mZnNldCwgdG1wc3RycHRyLCB0bXBwYXRwdHIsIHN0ciwgcGF0LCBmYWlsb2Zmc2V0KSkKCQkJCXJldHVybiB0cnVlOwoJCQlmYWlsb2Zmc2V0Lmluc2VydChtYWtlX3BhaXIoc3RhdGUsIG9mZnNldCArIHRoaXNvZmZzZXQpKTsKCQl9Cgl9CglmYWlsb2Zmc2V0Lmluc2VydChtYWtlX3BhaXIoc3RhdGUsIG9mZnNldCArIHRoaXNvZmZzZXQpKTsKCXJldHVybiBmYWxzZTsKfQoKYm9vbCBpc01hdGNoKGNvbnN0IGNoYXIqcywgY29uc3QgY2hhcipwKSB7Cgl2ZWN0b3I8Y2hhcj4gc3RyLCBwYXQ7Cgl1bm9yZGVyZWRfbXVsdGltYXA8aW50LCBpbnQ+IHVtOwoJY2xlYW51cChzLCBwLCBzdHIsIHBhdCk7CglpbnQgaSA9IDA7CglpbnQgaiA9IDA7Cgl3aGlsZSAoaSA8IHN0ci5zaXplKCkgJiYgaiA8IHBhdC5zaXplKCkpIHsKCQlpZiAoc3RyW2ldID09IHBhdFtqXSB8fCBwYXRbal0gPT0gJz8nKSB7CgkJCWkrKzsgaisrOwoJCQljb250aW51ZTsKCQl9CgkJaWYgKHBhdFtqXSA9PSAnKicpIGJyZWFrOwoJCXJldHVybiBmYWxzZTsKCX0KCWlmIChpID09IHN0ci5zaXplKCkpIHsKCQl3aGlsZSAoaiA8IHBhdC5zaXplKCkgJiYgcGF0W2pdID09ICcqJykgaisrOwoJCWlmIChqID09IHBhdC5zaXplKCkpIHJldHVybiB0cnVlOwoJCXJldHVybiBmYWxzZTsKCX0KCWlmIChqID09IHBhdC5zaXplKCkpIHJldHVybiBmYWxzZTsKCXN0ci5lcmFzZShzdHIuYmVnaW4oKSwgc3RyLmJlZ2luKCkgKyBpKTsKCXBhdC5lcmFzZShwYXQuYmVnaW4oKSwgcGF0LmJlZ2luKCkgKyBqKTsKCglyZXR1cm4gaGVscGVyKDAsIDAsIDAsIDAsIHN0ciwgcGF0LCB1bSk7Cn0KCmludCBtYWluKCkgewoJLy9jaGFyIHN0cltdID0gImFiY2RlZmciOwoJLy9jaGFyIHBhdFtdID0gImFiKmUqZipnKiI7CgljaGFyIHN0cjJbXSA9ICJhIjsKCWNoYXIgcGF0MltdID0gImEqIjsKCgljb3V0IDw8IGlzTWF0Y2goc3RyMiwgcGF0Mik7CgoJcmV0dXJuIDA7Cn0=