CQOI2014 通配符匹配
问题描述
几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号“*”,可以匹配0个即以上任意的字符;另一个是问号“?”,可以匹配恰好一个任意字符。
现在需要你编写一个程序,对于给定文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。
输入格式
第一行是一个由小写字母和上述通配符组成的字符串。
第二行包含一个整数n,表示文件的个数。
接下来n行,每行为一个仅含小写字母的字符串,表示文件名列表。
输出格式
输出n行,每行为“YES”或“NO”,表示对应文件能否被通配符匹配。
样例输入
abc?e*e
3
abcee
ppabcqexe
abcdefgee
样例输出
NO
YES
YES
提示
对于30%的数据,字符串长度不超过100
对于100%的数据,字符串长度不超过100000,1<=n<=100,通配符个数不超过10个。
这道题有贪心的做法,代码量更大,跑得更快,但是我不会。
通配符个数较少,考虑DP。设$bool$类型的$f[i][j]$表示用完前$i$个通配符,是否能完成1~$ j$位置的匹配。
分别考虑两种类型的通配符的转移。相同点是,两个通配符之间的字符串是必须完全相同的,这个可以用Hash来判断。
下面考虑$f[i][j]$的状态转移。设第$i$个通配符的位置是$pos[i]$,含有通配符的字符串是$s$,文件字符串是$t$。
- 第$i+1$个通配符是’?’。此时需要判断$s[pos[i]+1,pos[i+1]-1]$与$t[j+1,j+pos[i+1]-pos[i]-1]$是否相同。如果这部分相同,而且$f[i][j]$为真,那么$f[i+1][j+pos[i+1]-pos[i]]$为真,否则为假。注意这里是“$j+pos[i+1]-pos[i]$”而不是“$j+pos[i+1]-pos[i]-1$”,因为’?’本身也需要匹配。
- 第$i+1$个通配符是’*’。此时只要$s[pos[i]+1,pos[i+1]-1]$与$t[j+1,j+pos[i+1]-pos[i]-1]$相同,那么$t$之后的位置就都可以匹配了。所以对于这一部分,在匹配成功且$f[i][j]$为真的情况下,只需要把f[i+1][j+pos[i+1]-pos[i]-1]置为真,最后用一个循环$f[i+1][j]|=f[i+1][j-1]$即可。
为了方便处理,给$s$的末尾添加一个’?’,给$t$的末尾添加一个任意字符。
看起来时间复杂度爆炸($O(NKlen)$,$K$为分隔符个数),但是它竟然可过。或许是因为数据没有把字符串长度全部取满?
1 |
|