BZOJ3507通配符匹配(DP + Hash)
2017-08-29 19:02
309 查看
搬运题解系列:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5962702.html
Submit: 372 Solved: 156
[Submit][Status][Discuss]
几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符。
现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。
第一行是一个由小写字母和上述通配符组成的字符串。
第二行包含一个整数n,表示文件个数。
接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表。
输出n行,每行为“YES”或“NO”,表示对应文件能否被通配符匹配。
*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct
YES
YES
YES
YES
YES
NO
对于1 00%的数据
·字符串长度不超过1 00000
· 1 <=n<=100
·通配符个数不超过10
感觉复杂度有点玄学的做法。
DP+Hash
f[i][j]表示第i个通配符能否匹配到第j个位置。
因为一个*会把字符串分成两段,所以这个*分开的两边一定是要求一样的,这里可以利用hash判断。
然后我们就可以得到通配符串被*分成好几段,这样就可以得到转移。
枚举起点,如果可以匹配就可以转移。
有一些比较方便的处理,比如S最后加一个?,以及s最后加任意一个字符
这样的时间复杂度封顶大概是
O(N∗k∗len),但是发现这个转移其实时间复杂度是不满的,所以可以AC
3507: [Cqoi2014]通配符匹配
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 372 Solved: 156
[Submit][Status][Discuss]
Description
几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符。现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。
Input
第一行是一个由小写字母和上述通配符组成的字符串。第二行包含一个整数n,表示文件个数。
接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表。
Output
输出n行,每行为“YES”或“NO”,表示对应文件能否被通配符匹配。
Sample Input
*aca?ctc6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct
Sample Output
YESYES
YES
YES
YES
NO
HINT
对于1 00%的数据·字符串长度不超过1 00000
· 1 <=n<=100
·通配符个数不超过10
Source
Solution
感觉复杂度有点玄学的做法。DP+Hash
f[i][j]表示第i个通配符能否匹配到第j个位置。
因为一个*会把字符串分成两段,所以这个*分开的两边一定是要求一样的,这里可以利用hash判断。
然后我们就可以得到通配符串被*分成好几段,这样就可以得到转移。
枚举起点,如果可以匹配就可以转移。
有一些比较方便的处理,比如S最后加一个?,以及s最后加任意一个字符
这样的时间复杂度封顶大概是
O(N∗k∗len),但是发现这个转移其实时间复杂度是不满的,所以可以AC
#include<bits/stdc++.h> using namespace std; #define ULL unsigned long long #define LL long long #define MAXN 100010 #define BASE 131 char s1[MAXN],s2[MAXN]; ULL Hash[2][MAXN], pw[MAXN]; bool dp[12][MAXN]; int p[20], t, n; void Hashtable(char str[], int opt) { int len=strlen(str+1); for(int i=1; i<=len; i++) Hash[opt][i]=Hash[opt][i-1]*BASE+str[i]; } ULL GetHash(int l, int r, int opt) { return r>=l ? Hash[opt][r]-Hash[opt][l-1]*pw[r-l+1] : -1; } int main() { pw[0]=1;for(int i=1; i<MAXN; i++) pw[i]=pw[i-1]*BASE; scanf("%s", s1+1);Hashtable(s1, 0); int len=strlen(s1+1); for(int i=1; i <=len; i++) if(s1[i]=='*'||s1[i]=='?') p[++t]=i; p[++t]=++len;s1[len] = '?'; scanf("%d", &n); while(n--) { scanf("%s", s2+1);Hashtable(s2, 1); memset(dp, false, sizeof(dp));dp[0][0]=true; len = strlen(s2+1);s2[++len]='@'; for(int i=0; i <=t-1; i++) { if(s1[p[i]]=='*') for(int j=1; j<=len; j++) if(dp[i][j-1]) dp[i][j] = true; for(int j=0; j<=len; j++) if(dp[i][j]&&GetHash(j+1,j+(p[i+1]-1)-(p[i]+1)+1,1)==GetHash(p[i]+1, p[i+1]-1, 0)) if(s1[p[i+1]]=='?') dp[i+1][j+(p[i+1]-1)-(p[i]+1)+1+1]=true; else dp[i+1][j+(p[i+1]-1)-(p[i]+1)+1] = true; } if(dp[t][len]) puts("YES"); else puts("NO"); } return 0; }
相关文章推荐
- [CQOI2014][bzoj3507] 通配符匹配 [字符串hash+dp]
- [BZOJ3507]通配符匹配
- 【BZOJ-3507】通配符匹配 DP + Hash
- bzoj3507 [Cqoi2014]通配符匹配
- 【bzoj3570】 Cqoi2014—通配符匹配
- BZOJ 1264 Match 基因匹配 (dp 树状数组优化)
- bzoj 3197 [Sdoi2013]assassin(Hash+DP+KM)
- bzoj1264 [AHOI2006]基因匹配Match (树状数组优化DP)
- bzoj 3162: 独钓寒江雪 树形dp&hash
- dp+树状数组 bzoj1264 AHOI2006基因匹配
- [KM 树同构Hash DP] BZOJ 3197 [Sdoi2013]assassin
- bzoj1090 [SCOI2003]字符串折叠(区间dp+Hash)
- bzoj 1014 LCP 二分 Hash 匹配
- bzoj2547 [Ctsc2002]玩具兵 dp+二分匹配
- BZOJ 4503: 两个串 FFT 通配符匹配
- 【BZOJ1264】[AHOI2006]基因匹配Match【DP】【LCS】【树状数组】
- LeetCode-Wildcard Matching-通配符匹配-DP
- [BZOJ3214][ZJOI2013]丽洁体(Hash+DP)
- BZOJ 1264: [AHOI2006]基因匹配Match 树状数组,DP
- BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash