• 【HDOJ】3901 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] = '';
    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] = '';
    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.
    ", (int)clock());
    204     #endif
    205 
    206     return 0;
    207 }
  • 相关阅读:
    HTTP Status 404
    The error occurred while setting parameters--索引 3 超出范围 sqlserver2008
    hessian不能注入dao的问题解决
    怎么 才能显示Eclipse中Console的全部内容
    java mvc web 项目web.xml头改错了,死活加载不上springMvc的jar
    如何理解andriod中的View和framelayout两个概念
    Type Project has no default.properties file! Edit the project properties to set one.
    shell获取目录下(包括子目录)所有文件名、路径、文件大小
    找出1小时内占用cpu最多的10个进程的shell脚本
    awk统计命令(求和、求平均、求最大值、求最小值)
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5335292.html
Copyright © 2020-2023  润新知