【2020.11.25提高组模拟】太空漫步(walking) 题解

题目描述

Do not go gentle into that good night.

Old age should burn and rave at close of day.

Rage, Rage against the dying light.

不要温和地走进那个良夜。

白昼将尽,暮年仍应燃烧咆哮。

怒斥吧——怒斥光的消逝。

给一个固定的模式串和\(n\)个文本串,求对于每个文本串的所有前缀能否匹配成功。

模式串只包含NSEW和一些特殊字符*?[]

  • *表示一个不定长度的可空串,

  • ?表示一个不定的字符。

  • [A]代表可以出现也可以不出现。

  • NSEW是正常的字符。

例如,若模式串为NS*E,文本串有NSWE,那么文本串的所有前缀中只有NSWE能够匹配,输出0001。(0表示不成功,1表示成功)

\(n\le100,\mid S_{模式串}\mid\le100,\sum_{i-1}^n\mid s_i\mid\le10^6\)。

Solution

看上去答案应该会很暴力吧。

但是数据如此之大,暴力从哪里入手呢?

发现模式串长度非常之小,可以从这里入手。

设\(f[i][j]\)表示模式串的前\(i\)个和当前文本串的前\(j\)个能否匹配成功。

然后尝试转移:

  • 若\(p[i]\)为\(?\)或\(p[i]=t[j]\),那么\(f[i][j]\)可以从\(f[i-1][j-1]\)转移。

  • 若\(p[i]\)为\(*\),那么\(f[i][j]\)可以从\(f[i-1][j],f[i-1][j-1],f[i][j-1]\)转移。

  • 若\(p[i]\)为\([\),那么\(f[i][j]\)仍然是\(f[i-1][j]\)。

  • 若\(p[i]\)为\(]\),那么\(f[i][j]\)可以从\(f[i-1][j]\)转移,也可以从\(f[l[i]][j]\)转移。

其中\(l[x]\)表示与下标为\(x\)的\(]\)所匹配的\([\)的下标。这个先预处理好。

时间复杂度\(O(|S_{模式串}|\cdot\sum|s_i|)\)。

Code-String

由于我比较喜欢用STL,就酿成了代码稀烂的下场……

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
string p,t;
int n;
bool f[110][1000010];
int l[110],stac[110],top;
int main()
{
// freopen("walking.in","r",stdin);
// freopen("walking.out","w",stdout);
cin>>p;
n=read();
for(int i=0;i<p.size();i++)
{
if(p[i]=='[') stac[top++]=i+1;
if(p[i]==']') l[i+1]=stac[--top];
}
while(n--)
{
cin>>t;
f[0][0]=1;
for(int i=1;i<=p.size();i++)
for(int j=0;j<=t.size();j++)
{
f[i][j]=0;
if(p[i-1]=='*'||p[i-1]=='?'||p[i-1]==t[j-1]) if(j) f[i][j]|=f[i-1][j-1];
if(p[i-1]=='*'){if(j) f[i][j]|=f[i][j-1];f[i][j]|=f[i-1][j];}
if(p[i-1]=='[') f[i][j]|=f[i-1][j];
if(p[i-1]==']') f[i][j]|=f[i-1][j]|f[l[i]][j];
}
for(int i=1;i<=t.size();i++) putchar(f[p.size()][i]+'0'); putchar('\n');
}
return 0;
}

Code-char[]

补一发用\(char\)数组的,这下子下标就从\(1\)开始啦!

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
char p[110],t[1000010];
int psize,tsize;
int n;
bool f[110][1000010];
int l[110],stac[110],top;
int main()
{
// freopen("walking.in","r",stdin);
// freopen("walking.out","w",stdout);
scanf("%s",p+1);
psize=strlen(p+1);
n=read();
for(int i=1;i<=psize;i++)
{
if(p[i]=='[') stac[top++]=i;
if(p[i]==']') l[i]=stac[--top];
}
while(n--)
{
scanf("%s",t+1);
tsize=strlen(t+1);
f[0][0]=1;
for(int i=1;i<=psize;i++)
for(int j=0;j<=tsize;j++)
{
f[i][j]=0;
if(p[i]=='*'||p[i]=='?'||p[i]==t[j]) if(j) f[i][j]|=f[i-1][j-1];
if(p[i]=='*'){if(j) f[i][j]|=f[i][j-1];f[i][j]|=f[i-1][j];}
if(p[i]=='[') f[i][j]|=f[i-1][j];
if(p[i]==']') f[i][j]|=f[i-1][j]|f[l[i]][j];
}
for(int i=1;i<=tsize;i++) putchar(f[psize][i]+'0'); putchar('\n');
}
return 0;
}

【2020.11.25提高组模拟】太空漫步(walking) 题解的更多相关文章

  1. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  2. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  3. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  4. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  5. JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)

    题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...

  6. JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)

    题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...

  7. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  8. 【2020.12.03提高组模拟】A组反思

    估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...

  9. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  10. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

随机推荐

  1. 2022美亚杯个人赛wp(纯文字思路)

    2022美亚杯个人赛wp(纯文字思路) vc镜像密码CZDGm#&2_Ns$7wSMn%ZGr7xntcHS7d5uFta#Up9544jx_cvP$uFM7?pTDa*jN&QyFD ...

  2. 关于centos 7安装binwalk的过程中产生的问题

    啊,kali机坏了,又安的centos o(╥﹏╥)o 但是centos没有binwalk,它也不能像kali机一样之间install 又在网上搜教程 https://blog.csdn.net/qq ...

  3. 【P7&Loongson】支持部分中断/异常处理

    概况 常规单发射5级流水线cpu.新增支持指令{mtc0, mfc0, eret, syscall, break, bgezal, bltzal}:新增异常处理{Int, AdEL, AdES, Ov ...

  4. MIT 操作系统6.S081第一章

    1.1进程和内存 fork 父进程中 fork 返回 子进程的PID 子进程中 fork 返回 0 exit exit会让当前进程停止执行并释放资源(包括内存和打开的文件) 通常: 0 表示 成功 1 ...

  5. npm 如何更新项目最新依赖包

    NPM 是什么? Node 软件包管理器(NPM)提供了各种功能来帮助你安装和维护项目的依赖关系. 由于错误修复.新功能和其他更新,依赖关系可能会随着时间的推移而变得过时.你的项目依赖越多,就越难跟上 ...

  6. Mac下打开进入/usr/local等隐藏目录

    教程 Mac下/usr/local目录默认是对于Finder是隐藏,如果需要到/usr/local下去,打开Finder,然后使用command+shift+G,在弹出的目录中填写/usr/local ...

  7. Git提交历史优化指南:两步合并本地Commit,代码审查更高效!

    在开发过程中,频繁的本地Commit可能导致提交历史冗杂,增加代码审查和维护的复杂度.通过合并连续的Commit,不仅能简化历史记录,还能提升代码可读性和团队协作效率,以下是合并两次本地Commit的 ...

  8. SpringSecurity5(10-动态权限管理)

    授权流程 SpringSecurity 的授权流程如下: 拦截请求,已认证用户访问受保护的 web 资源将被 SecurityFilterChain 中的 FilterSecurityIntercep ...

  9. 继承的介绍、使用-java se进阶 day01

    1.继承的介绍 2.继承的使用 为什么要使用继承?假如以后要写一个项目,其中程序员一个类,项目经理一个类,Hr一个类,但是这些类的成员都一样 如图 我们会发现这些成员都是重复的,三个类都写重复的成员十 ...

  10. 支付宝当面付和微信付款码支付封装DLL

    项目中需要为客户对接支付宝的当面付和微信付款码支付.场景就是软件中生成金额订单,然后扫顾客的微信付款码或者支付宝的付款码完成收款.为此封装了此DLL,可以用在其他项目中,其他人也可以直接拿来用. 最主 ...