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代码:
#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的更多相关文章
- 【HDOJ】3901 Wildcard
1. 题目描述有两个长度为$10^5$的字符串,其中一个仅包含小写字母,称之为源串:另一个包含?与*通配符的模式串,并且通配符的个数不超过10.求模式串是否能匹配源串? 2. 基本思路这其实是一道Re ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 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 ...
- [LeetCode] Wildcard Matching 外卡匹配
Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
随机推荐
- .Net基础——程序集与CIL
1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll则需要被其他程序集调用执行. CIL ...
- [日常] Go-逐行读取文本信息
go逐行读取文本信息:1.os包提供了操作系统函数的不依赖平台的接口,Open方法打开一个文件用于读取,func Open(name string) (file *File, err error)2. ...
- Java开发笔记(七十一)容器工具Collections
清单作为一组数据的有序队列,它在组织形式上与数组有着某些异曲同工之处,数组有专门的数组工具Arrays来进行加工操作,照理清单也应该配备对应的清单工具.当然容器这个大家族确实拥有自己的容器工具Coll ...
- 【转】Android开发笔记(序)写在前面的目录
原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...
- AI书单
1.<TensorFlow实战> 黄文坚 2.<Machine Learning> [美]Tom Mitchell 3.<机器学习> 周志华
- 深入浅出Java类加载过程
学习笔记二之Java虚拟机中类加载的过程 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现这个类进行初始化. 1. 加载 加载,是指Java虚拟机查找字 ...
- js cookie存取
if(getCookie('guide') == 'true'){ window.location.href='' } else { setCookie('guide','true'); } func ...
- SAP MM 预留单据里的Base date和Requirement date
SAP MM 预留单据里的Base date和Requirement date Base date可以在预留创建的初始界面指定, 这个日期可以作为预留各个行项目默认的requirement date. ...
- arcgis api 3.x for js 入门开发系列二不同地图服务展示(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- Fragment 生命周期的详情
Fragment每个生命周期方法的意义.作用(注意红色的不是生命周期方法):setUserVisibleHint():设置Fragment可见或者不可见时会调用此方法.在该方法里面可以通过调用getU ...