鱼香rose'Blog

AtCoder Beginner Contest 329(E - Stamp)

AtCoder Beginner Contest 329

比赛地址:Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 329) - AtCoder

E - Stamp

Problem Statement

You are given two strings: \(S\), which consists of uppercase English letters and has length \(N\), and \(T\), which also consists of uppercase English letters and has length \(M\ (\leq N)\).

There is a string \(X\) of length \(N\) consisting only of the character #. Determine whether it is possible to make \(X\) match \(S\) by performing the following operation any number of times:

  • Choose \(M\) consecutive characters in \(X\) and replace them with \(T\).

Constraints

  • \(1 \leq N \leq 2\times 10^5\)
  • \(1 \leq M \leq \min(N,\) \(5\)\()\)
  • \(S\) is a string consisting of uppercase English letters with length \(N\).
  • \(T\) is a string consisting of uppercase English letters with length \(M\).

Input

The input is given from Standard Input in the following format:

\(N\) \(M\)
\(S\)
\(T\)

Output

Print Yes if it is possible to make \(X\) match \(S\); print No otherwise.

Sample Input 1

7 3
ABCBABC
ABC

Sample Output 1

Yes

Below, let \(X[l:r]\) denote the part from the \(l\)-th through the \(r\)-th character of \(X\).

You can make \(X\) match \(S\) by operating as follows.

  1. Replace \(X[3:5]\) with \(T\). \(X\) becomes ##ABC##.
  2. Replace \(X[1:3]\) with \(T\). \(X\) becomes ABCBC##.
  3. Replace \(X[5:7]\) with \(T\). \(X\) becomes ABCBABC.

题目大意

给定两个字符串\(S_1,S_2\),长度分别为\(n,m\),然后再给一个长度为\(n\)的字符串\(S_3\)\(S_3\)是全部由‘#’组成的字符串。

题目要求每次用\(S_2\)来覆盖\(S_3\)的一段连续的位置,判断是否可以将\(S_3\)构造成\(S_1\)

思路

我们可以将本题理解为粘胶带,我们可以将\(S_3\)看作是一个长度为\(n\)空白的板子,将\(S_2\)看作是一个长度为\(m\)且印有字母的胶带,这样每次操作就相当于在空白板子上粘胶带,而每次粘胶带时都会覆盖掉当前这段长度为\(m\)的位置,求最后是否能将该空白的板子粘成\(S_1\)的样子。

如果我们考虑根据粘胶带的顺序来判断是否能构造成\(S_1\),那么就会出现有后效性,即后续操作会影响当前操作。

于是换个思路来想,根据粘胶带的思路,无论怎么粘,最后一个粘的胶带都不会被遮挡,所以我们考虑倒着操作,将\(S_1\)胶带一张一张揭下来,最后判断是否能揭成一个空白的板子

因此我们枚举\(S_1\)中的子段\(S_2\),当然其中包含形如“AB#”,这种与“ABC”等价,因为第三个位置实际上是会被覆盖的。然后用dfs一层一层的揭,在dfs搜索的时候要注意,当前位置的前面和后面都要搜索一边,因为这个字符串可能被覆盖的前缀,也可能是后缀。

实现

#include<bits/stdc++.h>

using namespace std;

#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
#define LL long long 
#define ULL unsigned long long 
#define PII pair<int, int>
#define lowbit(x) (x & -x)
#define Mid ((l + r) >> 1)
#define ALL(x) x.begin(), x.end()
#define endl '\n'
#define fi first 
#define se second

const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const int N = 2e5 + 10; 

int n, m;
string s1, s2;

void modify(int x) {
    for(int i = x; i <= x + m - 1; i ++ ) {
        s1[i] = '#';
    }
}

bool check(int x) {
    bool flag = false;
    for(int i = 0; i < m; i ++ ) {
        if(s1[x + i] != s2[i]) {
            if(s1[x + i] != '#') {
                return false;
            }
        } else {
            flag = true;	//不能全为'#'
        }
    }
    return flag;
}

void dfs(int x) {
    modify(x);
    for(int i = x + 1; i < x + m && i < n; i ++ ) {
        if(check(i)) dfs(i);
    }
    for(int i = max(0, x - m + 1); i < x; i ++ ) {
        if(check(i)) dfs(i);
    }
}

void Solved() {
    cin >> n >> m;
    cin >> s1 >> s2;

    for(int i = 0; i < n - m + 1; i ++ ) {
        if(check(i)) dfs(i);
    }
    for(int i = 0; i < n; i ++ ) {
        if(s1[i] != '#') {
            cout << "No" << endl; return;
        }
    }
    cout << "Yes" << endl;
}

signed main(void) {
    IOS

    int ALL = 1; 
    // cin >> ALL;
    while(ALL -- ) Solved();

    return 0;
}
posted @ 2026-01-15 21:51  鱼香_rose  阅读(0)  评论(0)    收藏  举报