时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符。
现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。
输入描述:
第一行是一个由小写字母和上述通配符组成的字符串。
第二行包含一个整数n,表示文件个数。
接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表。
输出描述:
输出n行,每行为“YES”或“NO”,表示对应文件能否被通配符匹配。
示例1
输入
*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct
输出
YES
YES
YES
YES
YES
NO
对于1 00%的数据
字符串长度不超过1 00000
1 <=n<=100
通配符个数不超过10
用dp[i][j]表示主串S从第1个字符到第i个通配符间的子串是否与匹配串T从第1个字符到第j个字符间的子串相匹配,1表示匹配。
由于主串的最后一个字符串不一定是通配符'*'或'?',所以在主串后加一个通配符'?,匹配串后加一个任意的字符,这样问题的解就可以用dp[cnt][LT](cnt为主串通配符的个数,LT为匹配串的长度)来表示。
不含通配符的字符串匹配利用Hash判断
AC代码:
//CSDN博客:https://blog.csdn.net/qq_40889820
#include<iostream>
#include<sstream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#include<set>
#define mem(a,b) memset(a,b,sizeof(a))
#define random(a,b) (rand()%(b-a+1)+a)
#define ull unsigned long long
#define e 2.71828182
#define Pi 3.141592654
using namespace std;
const int MAXN=1e5+10;
const int Base=1e9+7;
char S[MAXN],T[MAXN];
int n,LS,LT,cnt;
int dp[13][MAXN];
int pos[13];//pos[i]表示主串中第i个通配符的位置
ull haS[MAXN],haT[MAXN],power[MAXN],htmp;
inline ull hash1(int l,int r)
{
if(l>r) return 0;
return haS[r]-haS[l-1]*power[r-l+1];
}
inline ull hash2(int l,int r)
{
if(l>r) return 0;
return haT[r]-haT[l-1]*power[r-l+1];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>(S+1)>>n;
LS=strlen(S+1);
S[++LS]='?';//在主串末尾加个'?'
power[0]=1;
for(int i=1;i<=MAXN;++i) power[i]=power[i-1]*Base;
for(int i=1;i<=LS;++i)
{
if(S[i]=='*'||S[i]=='?') pos[++cnt]=i;
haS[i]=haS[i-1]*Base+S[i]-'a'+1;
}
while(n--)
{
cin>>(T+1);
LT=strlen(T+1);
T[++LT]='.';//在匹配串末尾任意加个字符
haT[0]=0;
for(int i=1;i<=LT;++i)
haT[i]=haT[i-1]*Base+T[i]-'a'+1;
mem(dp,0);dp[0][0]=1;
for(int i=0;i<=cnt-1;++i)
{
if(S[pos[i]]=='*')//'*'可匹配0个至任意多个字符
{
for(int j=1;j<=LT;++j)
if(dp[i][j-1]) dp[i][j]=1;
}
htmp=hash1(pos[i]+1,pos[i+1]-1);
for(int j=0;j<=LT;++j)
{
if(dp[i][j]&&htmp==hash2(j+1,j+pos[i+1]-pos[i]-1))//pos[i+1]-1-(pos[i]+1)+1
{
if(S[pos[i+1]]=='?') dp[i+1][j+pos[i+1]-pos[i]]=1;//'?'可以与任意一个字符匹配
else dp[i+1][j+pos[i+1]-pos[i]-1]=1;
}
}
}
if(dp[cnt][LT]) cout<<"YES\n";
else cout<<"NO\n";
}
}