# 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-05 1239

08-19 1354

08-15 7612

08-26 37

12-13 192

08-08 507

03-10 30

08-04 3242

09-07 147

06-14 6万+

#### 楼天城楼教主的acm心路历程（作为励志用）

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。