HDOJ3901 Wildcard

Posted Bombe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ3901 Wildcard相关的知识,希望对你有一定的参考价值。

1. 题目描述
有两个长度为$10^5$的字符串,其中一个仅包含小写字母,称之为源串;另一个包含?与*通配符的模式串,并且通配符的个数不超过10。求模式串是否能匹配源串?

2. 基本思路
这其实是一道RegularExpression-Matching问题。一般化的解法就是构建自动机,然后去在这个自动机上搜索源串,是否被接收即为答案。这个一般化方法的时间复杂度为$O(|x||y|)$。显然,这里不适用。题目中的限定条件通配符个数不超过10使得,不需要构建完整的自动机。我们可以将模式串$d$改写为
$d_0 \cdot (?|*) \cdot d_1 \cdot (?|*) \cdots d_k$,其中$d_0, d_1, \cdots d_k$可以为$\varepsilon$。
因此,我们可以换一个思路。首先,利用kmp算法我们可以求得子串$d_i, i \in [0, k]$在源串$s$上的匹配位置,称之为end-point。
则对通配符分情况讨论:
(1) ?:仅匹配一个字符,那么d_k匹配的有效的end-point的下一个位置仍然可以匹配;
(2) *:可以匹配任意个字符,那么d_k首次匹配的end-point的后续位置都可以匹配。
注意,这里的有效有特殊含义,有效不仅要保证这次的子串$d_i$匹配end-point,同时一定要满足上一次的位置$end-point - |d_i|$同样是可以匹配的。
因此,算法的框架就变成了:
(1) 对模式串进行分割,分割点为?或*;
(2) 在源串中使用kmp算法搜索子串的end-point并且标记;
(3) 利用前次的匹配标记数组$ep$与kmp的标记$visit$共同确定这次的匹配标记;
(4) 对长度为0的字符串单独讨论;
(5) 对不含通配符的模式串,直接strcmp。

3. 代码

  1 /* 3901 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <cstdio>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cstring>
 17 #include <climits>
 18 #include <cctype>
 19 #include <cassert>
 20 #include <functional>
 21 #include <iterator>
 22 #include <iomanip>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,1024000")
 25 
 26 #define sti                set<int>
 27 #define stpii            set<pair<int, int> >
 28 #define mpii            map<int,int>
 29 #define vi                vector<int>
 30 #define pii                pair<int,int>
 31 #define vpii            vector<pair<int,int> >
 32 #define rep(i, a, n)     for (int i=a;i<n;++i)
 33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 34 #define clr                clear
 35 #define pb                 push_back
 36 #define mp                 make_pair
 37 #define fir                first
 38 #define sec                second
 39 #define all(x)             (x).begin(),(x).end()
 40 #define SZ(x)             ((int)(x).size())
 41 #define lson            l, mid, rt<<1
 42 #define rson            mid+1, r, rt<<1|1
 43 
 44 #ifndef ONLINE_JUDGE
 45 const int maxn = 100;
 46 #else
 47 const int maxn = 1e5+5;
 48 #endif
 49 const int maxm = 13;
 50 char s[maxn], d[maxn];
 51 bool ep[maxm][maxn];
 52 bool visit[maxn];
 53 char ss[maxn];
 54 int nxt[maxn], slen, dlen;
 55 
 56 void getnext(char *s, int len) {
 57     int i, j;
 58 
 59     nxt[0] = -1;
 60     i = 0;
 61     j = -1;
 62     while (i < len) {
 63         if (j==-1 || s[i]==s[j]) {
 64             ++i;
 65             ++j;
 66             nxt[i] = j;
 67         } else {
 68             j = nxt[j];
 69         }
 70     }
 71 }
 72 
 73 void findEndPoint(char *ss, int len) {
 74     int i = 0, j = 0;
 75 
 76     getnext(ss, len);
 77     memset(visit, false, sizeof(visit));
 78     while (i < slen) {
 79         if (s[i] == ss[j]) {
 80             ++i;
 81             ++j;
 82         } else {
 83             j = nxt[j];
 84             if (j == -1) {
 85                 j = 0;
 86                 ++i;
 87             }
 88         }
 89         if (j == len) {
 90             visit[i] = true;
 91         }
 92     }
 93 }
 94 
 95 void solve() {
 96     slen = strlen(s);
 97     dlen = strlen(d);
 98     int gid = 0;
 99     int i = 0, l = 0;
100 
101     {
102         // fast check
103         bool flag = true;
104         rep(k, 0, dlen) {
105             if (d[k]==? || d[k]==*) {
106                 flag = false;
107                 break;
108             }
109         }
110 
111         if (flag) {
112             if (strcmp(s,d)==0)
113                 puts("YES");
114             else
115                 puts("NO");
116             return ;
117         }
118     }
119 
120     memset(ep, false, sizeof(ep));
121     ep[gid++][0] = true;
122     while (i < dlen) {
123         if (islower(d[i])) {
124             ss[l++] = d[i++];
125             continue;
126         }
127 
128         ss[l] = \0;
129         if (d[i]==?) {
130             if (l == 0) {
131                 rep(i, 0, slen+1)
132                     ep[gid][i+1] = ep[gid-1][i];
133             } else {
134                 findEndPoint(ss, l);
135                 rep(i, 0, slen+1) {
136                     if (ep[gid-1][i] && visit[i+l]) {
137                         ep[gid][i+l+1] = true;
138                     }
139                 }
140             }
141         } else if (d[i]==*) {
142             if (l == 0) {
143                 int fir = slen+1;
144                 rep(i, 0, slen+1) {
145                     if (ep[gid-1][i]) {
146                         fir = i;
147                         break;
148                     }
149                 }
150 
151                 rep(i, fir, slen+1)
152                     ep[gid][i] = true;
153             } else {
154                 findEndPoint(ss, l);
155                 int fir = slen + 1;
156                 rep(i, 0, slen+1) {
157                     if (ep[gid-1][i] && visit[i+l]) {
158                         fir = i + l;
159                         break;
160                     }
161                 }
162 
163                 rep(i, fir, slen+1)
164                     ep[gid][i] = true;
165             }
166         }
167 
168         l = 0;
169         ++gid;
170         ++i;
171     }
172 
173     if (l > 0) {
174         ss[l] = \0;
175         findEndPoint(ss, l);
176         rep(i, 0, slen+1) {
177             if (ep[gid-1][i] && visit[i+l]) {
178                 ep[gid][i+l] = true;
179             }
180         }
181         ++gid;
182     }
183 
184     if (ep[gid-1][slen])
185         puts("YES");
186     else
187         puts("NO");
188 }
189 
190 int main() {
191     ios::sync_with_stdio(false);
192     #ifndef ONLINE_JUDGE
193         freopen("data.in", "r", stdin);
194         freopen("data.out", "w", stdout);
195     #endif
196 
197     while (scanf("%s", s)!=EOF) {
198         scanf("%s", d);
199         solve();
200     }
201 
202     #ifndef ONLINE_JUDGE
203         printf("time = %d.\n", (int)clock());
204     #endif
205 
206     return 0;
207 }

 

以上是关于HDOJ3901 Wildcard的主要内容,如果未能解决你的问题,请参考以下文章

什么是反掩码wildcard-mask ?

makefile中wildcard判断文件存在

第八周 Leetcode 44. Wildcard Matching 水题 (HARD)

ssl wildcard 怎么样

wildcard是啥意思

[Luogu 3901]Difference