# hdu 3901 Wildcard 带通配符的字符串匹配

Problem Description
When specifying file names (or paths) in DOS, Microsoft Windows and Unix-like operating systems,  the asterisk character (“*") substitutes for any zero or more characters, and the  question mark (“?") substitutes for any one character.
Now give you a text and a pattern, you should judge whether the pattern matches the text or not.

Input
There are several cases. For each case, only two lines. The first line contains a text, which contains only lower letters. The last line contains a pattern, which consists of lower letters and the two wildcards (“*", "?").
The text is a non-empty string and its size is less than 100,000, so do the pattern.

Output
Output “YES” if the pattern matches the text, otherwise “NO”.

Sample Input

abcdef
a*c*f


Sample Output

YES



//

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 120000;
char pat[maxn], text[maxn];

int fail[maxn];
//text 是否包含 pat
void makefail(char *t, int lt){
--t;
for(int i = 1, j = 0; i <= lt; i++, j++){
fail[i] = j;
while(j > 0 && t[i] != '?' && t[j] != '?' && t[i] != t[j])
j = fail[j];
}
}
int kmp(char *s, int ls, char *t, int lt, int i){
--s, --t; ++i;
for(int j = 1; i <= ls; i++, j++){
while(j > 0 && t[j] != '?' && s[i] != t[j])j = fail[j];
if(j == lt)return i - lt;
}
return -1;
}

bool wildMatch(char * pat, int lp, char * text, int lt){
//处理不含有 * 的情况
bool star = false;
for(int i = 0; i < lp && !star; i++)
if(pat[i]=='*')star = true;
if(!star){
if(lp != lt)return false;
for(int i = 0; i < lp; i++)
if(pat[i] != '?' && pat[i] != text[i])return false;
return true;
}

//处理前缀和后缀
int l0 = 0, l1 = 0;
for(int i = 0; pat[i] != '*'; i++){
if(i >= lt || pat[i] != '?' && pat[i] != text[i])return false;
l0 ++;
}
for(int i = 0; pat[lp - 1 - i] != '*'; i++){
if(i >= lt || pat[lp - 1 - i] != '?' && pat[lp - 1 - i] != text[lt - 1 - i])
return false;
l1++;
}
if(l0 + l1 > lt)return false;

//处理以*开始并且以*结束的部分
int offP = l0, offT = l0;
for(int i = l0; i < lp - l1; i++){
if(pat[i]=='*'){
int plen = i - offP;
if(plen > 0){
makefail(pat + offP, plen);
int match = kmp(text, lt - l1, pat + offP, plen, offT);
if(match == -1)return false;
offT = match + plen;
}
offP = i + 1;
}
}
return true;
}

int main(){
while( gets(text) )
{
gets(pat);
if( wildMatch(pat, strlen(pat), text, strlen(text) ) )
puts("YES");
else
puts("NO");
}
}

08-08 521

08-05 1258
08-04 3278
09-30 67
10-25 2515
07-16 961
04-19 154
03-05 2万+
10-04 1631
11-23 914
08-04 479
02-21 249
01-29 902
08-27 1422
08-16 1763