[ABC287D] Match or Not 题解

发布时间 2023-05-25 22:00:02作者: Bloodstalk

Description

翻译给的很明白了,就是让你判断 \(S\) 串的前 \(x(0 \leq x \leq |T|)\) 个字符和后 \(|T|-x\) 个字符组成的字符串和 \(T\) 串是否相等,其中问号能代替所有字母。

Solution

很有意思的一道题。

首先我们可以知道,如果前 \(i-1\) 位不能匹配的话,那么第 \(i\) 位不管它本身成功匹配与否,整个串是不匹配的。因此,我们可以很自然地想到递推求解(也可以说是前缀和)。

我们设 \(pre_i\) 表示 \(S\) 串的前 \(i\) 位是否和 \(T\) 串匹配,设 \(suf_i\) 表示 \(S\) 串的 \(i-|S|\) 位是否和 \(T\) 串匹配。等到最后统计答案的时候就判断 \(pre_i\)\(suf_{|S|-|T|+i+1}\) 是否都能成功匹配即可。

初始值 \(pre_0=1\)\(suf_{|S|+1}=1\)

接下来考虑怎么求出 \(pre\) 数组,其实也很简单:

  • 如果 \(pre_{i-1} = 0\) ,那么显然 \(pre_i = 0\) ( \(0\) 表示匹配不成功, \(1\) 表示匹配成功);

  • 如果等于 \(1\) ,我们需要判断这一位能不能匹配,有两种可能:

    (1):这一位字母本身就是相等的;

    (2):这两个字母中至少有一个问号。

    满足这两个条件,这一位就是匹配的了。

通过这个我们就可以求解这个问题了,\(suf\) 数组也是同理,只不过是反过来了。

Code

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define next nxt
#define re register
#define il inline
const int N = 3e5 + 5;
using namespace std;
int max(int x,int y){return x > y ? x : y;}
int min(int x,int y){return x < y ? x : y;}

char s[N],t[N];
int n,m,pre[N],suf[N];

il int read()
{
	int f=0,s=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) f |= (ch=='-');
	for(; isdigit(ch);ch=getchar()) s = (s<<1) + (s<<3) + (ch^48);
	return f ? -s : s;
}

signed main()
{
	cin >> s+1 >> t+1;
	pre[0] = 1;
	n = strlen(s+1) , m = strlen(t+1);
	for(re int i=1;i<=m;i++) if((s[i] == t[i] || (s[i] == '?' || t[i] == '?')) && pre[i-1]) pre[i] = 1; else pre[i] = 0;
	suf[n+1] = 1;
	for(re int i=n,j=m;i>=n-m+1;i--,j--) if((s[i] == t[j] || (s[i] == '?' || t[j] == '?')) && suf[i+1]) suf[i] = 1; else suf[i] = 0;
	for(re int i=0;i<=m;i++) if(pre[i] == 1 && suf[n-m+i+1] == 1) puts("Yes"); else puts("No");
	return 0;
}