【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;
}
posted @ 2020-11-26 15:39  Vanilla_chan  阅读(206)  评论(0)    收藏  举报