【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;
}