• HDU 3901 Wildcard


    题目:Wildcard

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3901

    题意:给一个原串(只含小写字母)和一个模式串(含小写字母、?、* ,*号可替换为0到无穷个任意字母,?可替换为一个任意字母),问两个字符串是否匹配。

    思路:

      这是经典题吧。。。

      AC自动机。(网上大多代码是错的,用普通kmp是不行的,不知道修改过后可不可以)。

      HDU已经加强数据了,可我前一个代码abcd ?显示是YES居然还过了,看来数据还是有点弱啊。

      *号的处理是很容易的,只需要把模式串以*号为分界分解开来,然后除了最后一段,其他尽量匹配靠前的原串子串就差不多了,比如ab*cd*ef*gh,那么原串必须以ab开头、gh结尾、然后找到最前的cd、再找到ef,如果互相不重叠就OK。

      比较难的是?的处理了,*分解开模式串分别处理。现在,根据?分解,将分解后的字符串(不含?号了)构建AC自动机。

      比如串A:abcd?abc?cd?abcd,构建AC自动机,然后在结束点记录他在串A中的位置。

      红色为根,黄色为每一个结束点,这里的fail指针与普通AC自动机相同

      现在我们创建一个数组cnt,对应原串的每一位,让原串在自动机上跑,如果遇到黄点cnt[当前位置-记录的值+1]++,比如遇到abcd,那说明原串当前位置前四位一定是abcd,满足这一段,而如果有某一个cnt值等于4,就说明他满足了所有段,那么他可以作为串A匹配的起点,a b c d _ a b c _ c d _ a b c d,只有上面这种情况才会使第一个a的cnt值为4,而cnt等于4,当前位就是该次匹配满足的最前位置了。

      上一段理解后,题目就可以得解了,注意细节就是了。

    AC代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #include<math.h>
      5 #include<set>
      6 #include<map>
      7 #include<list>
      8 #include<stack>
      9 #include<queue>
     10 #include<vector>
     11 #include<string>
     12 #include<iostream>
     13 #include<algorithm>
     14 using namespace std;
     15 #define lson rt<<1
     16 #define rson rt<<1|1
     17 #define N 100010
     18 #define M 26
     19 #define Mod 1000000007
     20 #define LL long long
     21 #define INF 0x7fffffff
     22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
     23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
     24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
     25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
     26 #define MT(x,i) memset(x,i,sizeof(x))
     27 #define gcd(x,y) __gcd(x,y)
     28 const double PI = acos(-1);
     29 
     30 struct Node
     31 {
     32   vector<int> d;
     33   int fail;
     34   int next[M];
     35 }v[N];
     36 int vNum;
     37 
     38 void Init()
     39 {
     40   v[0].fail = -1;
     41   FOR(i,0,25){
     42     v[0].next[i]=-1;
     43   }
     44   vNum=1;
     45 }
     46 
     47 int create()
     48 {
     49   v[vNum].d.clear();
     50   v[vNum].fail=-1;
     51   for(int i=0;i<M;i++) v[vNum].next[i]=-1;
     52   return vNum++;
     53 }
     54 
     55 int getPos(char c)
     56 {
     57   return c-'a';
     58 }
     59 
     60 int add(char *s)
     61 {
     62   int i,ret=0,p=0;
     63   for(i=0;s[i];i++){
     64     if(s[i]=='?'){
     65       if(p!=0){
     66         ret++;
     67         v[p].d.push_back(i);
     68         p=0;
     69       }
     70     }
     71     int pos = getPos(s[i]);
     72     if(v[p].next[pos]==-1) v[p].next[pos]=create();
     73     p = v[p].next[pos];
     74   }
     75   if(p!=0){
     76     ret++;
     77     v[p].d.push_back(i);
     78   }
     79   return ret;
     80 }
     81 
     82 queue<int> q;
     83 void makeFail()
     84 {
     85   q.push(0);
     86   while(q.size())
     87   {
     88     int p=q.front();
     89     q.pop();
     90     for(int i=0;i<M;i++)
     91     {
     92       if(v[p].next[i]!=-1)
     93       {
     94         int t=v[p].fail;
     95         while(1)
     96         {
     97           if(t == -1)  // p 已经是根了
     98           {
     99             v[v[p].next[i] ].fail = 0;
    100             break;
    101           }
    102           else if(v[t].next[i] != -1)
    103           {
    104             v[v[p].next[i] ].fail = v[t].next[i];
    105             break;
    106           }
    107           else t=v[t].fail;
    108         }
    109         if(t!=-1){
    110           for(int j=0;j<v[t].d.size();j++){
    111             v[p].d.push_back(v[t].d[j]);
    112           }
    113         }
    114         q.push(v[p].next[i]);
    115       }
    116     }
    117   }
    118 }
    119 
    120 int cnt[N];
    121 int match(char *s,char *s1)
    122 {
    123   Init();
    124   int duan = add(s1);
    125   if(duan==0) return 0;
    126 
    127   makeFail();
    128 
    129   //printf("%s %s %d
    ",s,s1,duan);
    130 
    131   memset(cnt,0,sizeof(cnt));
    132   int i,p=0;
    133   for(i=0;s[i];i++){
    134     int pos = getPos(s[i]);
    135     if(p==-1){
    136       p=0;
    137       continue;
    138     }
    139     if(v[p].next[pos]==-1){
    140       p = v[p].fail;
    141       i--;
    142       continue;
    143     }
    144     p = v[p].next[pos];
    145     for(int j=0;j<v[p].d.size();j++){
    146       cnt[i-v[p].d[j]+1]++;
    147       if(cnt[i-v[p].d[j]+1]==duan) return i-v[p].d[j]+1;
    148     }
    149   }
    150   return -1;
    151 }
    152 
    153 char s[N],s1[N],s2[N];
    154 bool solve(char *s,char *s1)
    155 {
    156   int ls=strlen(s),ps=0;
    157   int i,len=0,flag=0;
    158   for(i=0;s1[i];i++){
    159     if(s1[i]=='*'){
    160       if(len!=0){
    161         s2[len]=0;
    162         int qi = match(s+ps,s2);
    163         if(qi==-1) return false;
    164         if(flag==0 && qi!=0) return false;
    165         ps += qi + len;
    166         if(ps>ls) return false;
    167         len = 0;
    168       }
    169       flag=1;
    170     }
    171     else s2[len++]=s1[i];
    172   }
    173   if(len!=0){
    174     len--;
    175     for(i=ls-1;i>=ps && len>=0;i--){
    176       if(s2[len]!='?' && s2[len]!=s[i]) return false;
    177       len--;
    178     }
    179     if(i>=ps && flag==0 || len>=0) return false;
    180   }
    181   return true;
    182 }
    183 
    184 int main()
    185 {
    186   while(scanf("%s%s",s,s1)!=EOF)
    187   {
    188     printf("%s
    ",solve(s,s1)?"YES":"NO");
    189   }
    190   return 0;
    191 }
  • 相关阅读:
    汉语-词语:慧根
    汉语-词语:悟性
    汉语-汉字:耑
    汉语-汉字:羣
    汉语-词语:觉察
    汉语-词语:醒悟
    汉语-词语:觉悟
    Redhat 5禁止IPv6
    从缓存行出发理解volatile变量、伪共享False sharing、disruptor
    【故障处理141119】一次数据库不繁忙时一条sql语句2个运行计划导致业务超时的故障处理
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5925011.html
Copyright © 2020-2023  润新知