题目: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. linux查看和修改PATH环境变量的方法

    查看PATH:echo $PATH以添加mongodb server为列修改方法一:export PATH=/usr/local/mongodb/bin:$PATH//配置完后可以通过echo $PA ...

  2. [android]android下apk的安装过程

    /********************2016年4月23日更新********************************/ 知乎:有什么apk分析工具? 拿到了一个apk文件,怀疑不安全,在 ...

  3. Java学习笔记——判断字符Character类

    常用方法 下面所说的均是静态方法,也就是可以不创建对象直接调用 例:Character.isLetter(char c); isLetter 判断参数是否为字母(不分大小写),返回结果 isDigit ...

  4. tf.nn.conv2d。卷积函数

    tf.nn.conv2d是TensorFlow里面实现卷积的函数,参考文档对它的介绍并不是很详细,实际上这是搭建卷积神经网络比较核心的一个方法,非常重要 tf.nn.conv2d(input, fil ...

  5. WEB前端 CSS(非布局)

    目录 WEB前端 CSS CSS引入方式 CSS结构 CSS选择器 直接选择器 组合选择器 分组选择器 也叫并集选择器 属性选择器 伪类选择器 伪元素选择器 CSS选择器是一个查找的过程,高效的查找影 ...

  6. 高效使用VSCode的9点建议

    在开源 IDE 市场,最近几年 Visual Studio Code(简称 VSCode)越来越流行.自从 2015 年对外发布后,根据 2018 年 Stack Overflow 的调查报告,有 3 ...

  7. Node.js面试题之2017

    译者按: 从ECMAScript标准,Node.js语法以及NPM模块角度来看,Node.js的发展让人目不暇接,那么面试题也得与时俱进. 原文: Node.js Interview Question ...

  8. Html和Css学习笔记-css进阶-盒模型

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 此篇博客是我的复习笔记,html和css学的时间太久了,忘得差不多了,最近要使用一下,所以重新打开html的书略读,后记录了标签 ...

  9. bootstrap-treeview 树形菜单带复选框以及级联选择

    <div id="searchTree"></div> <script> var treeData = [{ text: "Paren ...

  10. jsp+servlet include引入文件指令

    1.index.jsp为首页 <%@ page contentType="text/html;charset=UTF-8" import="java.util.*& ...