【2020.11.25提高组模拟】太空漫步(walking) 题解
【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) 题解的更多相关文章
- 【2020.11.28提高组模拟】T1染色(color)
[2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...
- 【2020.11.28提高组模拟】T2 序列(array)
序列(array) 题目描述 给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...
- 【2020.11.30提高组模拟】剪辣椒(chilli)
剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...
- 【2020.11.30提高组模拟】删边(delete)
删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...
- JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)
题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...
- JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)
题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...
- 11.5NOIP2018提高组模拟题
书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...
- 【2020.12.03提高组模拟】A组反思
估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...
- 【2020.12.01提高组模拟】卡特兰数(catalan)
题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...
- 【2020.12.01提高组模拟】A组反思
105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...
随机推荐
- 2022美亚杯个人赛wp(纯文字思路)
2022美亚杯个人赛wp(纯文字思路) vc镜像密码CZDGm#&2_Ns$7wSMn%ZGr7xntcHS7d5uFta#Up9544jx_cvP$uFM7?pTDa*jN&QyFD ...
- 关于centos 7安装binwalk的过程中产生的问题
啊,kali机坏了,又安的centos o(╥﹏╥)o 但是centos没有binwalk,它也不能像kali机一样之间install 又在网上搜教程 https://blog.csdn.net/qq ...
- 【P7&Loongson】支持部分中断/异常处理
概况 常规单发射5级流水线cpu.新增支持指令{mtc0, mfc0, eret, syscall, break, bgezal, bltzal}:新增异常处理{Int, AdEL, AdES, Ov ...
- MIT 操作系统6.S081第一章
1.1进程和内存 fork 父进程中 fork 返回 子进程的PID 子进程中 fork 返回 0 exit exit会让当前进程停止执行并释放资源(包括内存和打开的文件) 通常: 0 表示 成功 1 ...
- npm 如何更新项目最新依赖包
NPM 是什么? Node 软件包管理器(NPM)提供了各种功能来帮助你安装和维护项目的依赖关系. 由于错误修复.新功能和其他更新,依赖关系可能会随着时间的推移而变得过时.你的项目依赖越多,就越难跟上 ...
- Mac下打开进入/usr/local等隐藏目录
教程 Mac下/usr/local目录默认是对于Finder是隐藏,如果需要到/usr/local下去,打开Finder,然后使用command+shift+G,在弹出的目录中填写/usr/local ...
- Git提交历史优化指南:两步合并本地Commit,代码审查更高效!
在开发过程中,频繁的本地Commit可能导致提交历史冗杂,增加代码审查和维护的复杂度.通过合并连续的Commit,不仅能简化历史记录,还能提升代码可读性和团队协作效率,以下是合并两次本地Commit的 ...
- SpringSecurity5(10-动态权限管理)
授权流程 SpringSecurity 的授权流程如下: 拦截请求,已认证用户访问受保护的 web 资源将被 SecurityFilterChain 中的 FilterSecurityIntercep ...
- 继承的介绍、使用-java se进阶 day01
1.继承的介绍 2.继承的使用 为什么要使用继承?假如以后要写一个项目,其中程序员一个类,项目经理一个类,Hr一个类,但是这些类的成员都一样 如图 我们会发现这些成员都是重复的,三个类都写重复的成员十 ...
- 支付宝当面付和微信付款码支付封装DLL
项目中需要为客户对接支付宝的当面付和微信付款码支付.场景就是软件中生成金额订单,然后扫顾客的微信付款码或者支付宝的付款码完成收款.为此封装了此DLL,可以用在其他项目中,其他人也可以直接拿来用. 最主 ...