【题目描述】:
几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符。
现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。
字符串长度不超过100000
1<=n<=100
通配符个数不超过10
【题目描述】:
《感觉复杂度不对系列》
我们考虑一个一个的去匹配
考虑动态规划,我们用f[i][j]表示模板串前i个和匹配串前j的是否可以匹配,根据对应字符匹配即可
然后这样做的复杂度是O(|S|^2),显然会MLE+TLE
我们考虑对于不包含通配符的模板串,我们直接KMP一下,然后DP转移即可
即:如果模板串在匹配串中成功匹配的起点为i,长度为len,那么f[next][i+len-1]|=f[cur][i]
然后我们考虑对于'?',显然f[next][i]|=f[cur][i-1]
对于'*',我们找到第一个f[cur][i]为true的,然后将f[next][i...n]全部变成true
考虑这样做的复杂度,这样做相当于把不含通配符的一段当成一个字符来处理,由于最多只有10个通配符,那么压缩后的字符串长度不超过20
因此复杂度就是O(|S|*20),|S|=100000
恩恩,看起来很靠谱滴样子,等等外面还有个N=100
时间复杂度O(N*|S|*20) TAT
不管了,写一发,然后A了不科学啊TAT
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100005;
int n,m,lena,lenb; bool f[2][N];
char s[N],a[N],b[N]; int p[N],cnt,pos[N];
inline long long getint()
{
long long x=0; char c=getchar(); bool flag=false;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') flag=true,c=getchar();
while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
if (flag) return -x; else return x;
}
void init()
{
scanf("%s",s+1); n=strlen(s+1);
}
inline void KMP()
{
cnt=0; p[1]=0;
for (int i=2,j=0; i<=lena; i++)
{
for (;(j>0)&&(a[i]!=a[j+1]);j=p[j]);
if (a[i]==a[j+1]) j++; p[i]=j;
}
for (int i=1,j=0; i<=lenb; i++)
{
for (;(j>0)&&(b[i]!=a[j+1]);j=p[j]);
if (b[i]==a[j+1]) j++;
if (j==lena) pos[++cnt]=i-lena+1,j=p[j];
}
}
bool judge()
{
memset(f,false,sizeof(f));
int cur=0,next=1; f[cur][0]=true;
for (int i=1,j=0; i<=n; i=j,swap(cur,next))
{
memset(f[next],false,sizeof(f[next]));
if (s[i]=='*')
{
for (j=0; j<=lenb; j++) if (f[cur][j]) break;
if (j==lenb+1) {j=i+1; continue;}
for (int k=j; k<=lenb; k++) f[next][k]=true;
j=i+1; continue;
}
if (s[i]=='?')
{
for (int k=0; k<=lenb-1; k++) f[next][k+1]|=f[cur][k];
j=i+1; continue;
}
for (j=i,lena=0; (j<=n)&&(s[j]!='*')&&(s[j]!='?'); j++) a[++lena]=s[j]; KMP();
for (int k=1; k<=cnt; k++) f[next][pos[k]+lena-1]|=f[cur][pos[k]-1];
}
return f[cur][lenb];
}
void solve()
{
m=getint();
for (int i=1; i<=m; i++)
{
scanf("%s",b+1); lenb=strlen(b+1);
if (judge()) printf("YES\n"); else printf("NO\n");
}
}
int main()
{
init();
solve();
return 0;
}