题目: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代码:

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
#define N 100010
#define M 26
#define Mod 1000000007
#define LL long long
#define INF 0x7fffffff
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
#define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
#define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
#define MT(x,i) memset(x,i,sizeof(x))
#define gcd(x,y) __gcd(x,y)
const double PI = acos(-); struct Node
{
vector<int> d;
int fail;
int next[M];
}v[N];
int vNum; void Init()
{
v[].fail = -;
FOR(i,,){
v[].next[i]=-;
}
vNum=;
} int create()
{
v[vNum].d.clear();
v[vNum].fail=-;
for(int i=;i<M;i++) v[vNum].next[i]=-;
return vNum++;
} int getPos(char c)
{
return c-'a';
} int add(char *s)
{
int i,ret=,p=;
for(i=;s[i];i++){
if(s[i]=='?'){
if(p!=){
ret++;
v[p].d.push_back(i);
p=;
}
}
int pos = getPos(s[i]);
if(v[p].next[pos]==-) v[p].next[pos]=create();
p = v[p].next[pos];
}
if(p!=){
ret++;
v[p].d.push_back(i);
}
return ret;
} queue<int> q;
void makeFail()
{
q.push();
while(q.size())
{
int p=q.front();
q.pop();
for(int i=;i<M;i++)
{
if(v[p].next[i]!=-)
{
int t=v[p].fail;
while()
{
if(t == -) // p 已经是根了
{
v[v[p].next[i] ].fail = ;
break;
}
else if(v[t].next[i] != -)
{
v[v[p].next[i] ].fail = v[t].next[i];
break;
}
else t=v[t].fail;
}
if(t!=-){
for(int j=;j<v[t].d.size();j++){
v[p].d.push_back(v[t].d[j]);
}
}
q.push(v[p].next[i]);
}
}
}
} int cnt[N];
int match(char *s,char *s1)
{
Init();
int duan = add(s1);
if(duan==) return ; makeFail(); //printf("%s %s %d\n",s,s1,duan); memset(cnt,,sizeof(cnt));
int i,p=;
for(i=;s[i];i++){
int pos = getPos(s[i]);
if(p==-){
p=;
continue;
}
if(v[p].next[pos]==-){
p = v[p].fail;
i--;
continue;
}
p = v[p].next[pos];
for(int j=;j<v[p].d.size();j++){
cnt[i-v[p].d[j]+]++;
if(cnt[i-v[p].d[j]+]==duan) return i-v[p].d[j]+;
}
}
return -;
} char s[N],s1[N],s2[N];
bool solve(char *s,char *s1)
{
int ls=strlen(s),ps=;
int i,len=,flag=;
for(i=;s1[i];i++){
if(s1[i]=='*'){
if(len!=){
s2[len]=;
int qi = match(s+ps,s2);
if(qi==-) return false;
if(flag== && qi!=) return false;
ps += qi + len;
if(ps>ls) return false;
len = ;
}
flag=;
}
else s2[len++]=s1[i];
}
if(len!=){
len--;
for(i=ls-;i>=ps && len>=;i--){
if(s2[len]!='?' && s2[len]!=s[i]) return false;
len--;
}
if(i>=ps && flag== || len>=) return false;
}
return true;
} int main()
{
while(scanf("%s%s",s,s1)!=EOF)
{
printf("%s\n",solve(s,s1)?"YES":"NO");
}
return ;
}

HDU 3901 Wildcard的更多相关文章

  1. 【HDOJ】3901 Wildcard

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

  2. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'mvc:annotation-driven'.

    spring 配置文件报错报错信息:cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be ...

  4. [LeetCode] Wildcard Matching 外卡匹配

    Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...

  5. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  6. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  7. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

随机推荐

  1. .Net基础——程序集与CIL

    1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll则需要被其他程序集调用执行. CIL ...

  2. [日常] Go-逐行读取文本信息

    go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...

  3. Java开发笔记(七十一)容器工具Collections

    清单作为一组数据的有序队列,它在组织形式上与数组有着某些异曲同工之处,数组有专门的数组工具Arrays来进行加工操作,照理清单也应该配备对应的清单工具.当然容器这个大家族确实拥有自己的容器工具Coll ...

  4. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  5. AI书单

    1.<TensorFlow实战>   黄文坚 2.<Machine Learning> [美]Tom Mitchell 3.<机器学习> 周志华  

  6. 深入浅出Java类加载过程

    学习笔记二之Java虚拟机中类加载的过程 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现这个类进行初始化. 1.    加载 加载,是指Java虚拟机查找字 ...

  7. js cookie存取

    if(getCookie('guide') == 'true'){ window.location.href='' } else { setCookie('guide','true'); } func ...

  8. SAP MM 预留单据里的Base date和Requirement date

    SAP MM 预留单据里的Base date和Requirement date Base date可以在预留创建的初始界面指定, 这个日期可以作为预留各个行项目默认的requirement date. ...

  9. arcgis api 3.x for js 入门开发系列二不同地图服务展示(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  10. Fragment 生命周期的详情

    Fragment每个生命周期方法的意义.作用(注意红色的不是生命周期方法):setUserVisibleHint():设置Fragment可见或者不可见时会调用此方法.在该方法里面可以通过调用getU ...