CF1553D Backspace(双指针)
You are given two strings 𝑠s and 𝑡t, both consisting of lowercase English letters. You are going to type the string 𝑠s character by character, from the first character to the last one.
When typing a character, instead of pressing the button corresponding to it, you can press the "Backspace" button. It deletes the last character you have typed among those that aren't deleted yet (or does nothing if there are no characters in the current string). For example, if 𝑠s is "abcbd" and you press Backspace instead of typing the first and the fourth characters, you will get the string "bd" (the first press of Backspace deletes no character, and the second press deletes the character 'c'). Another example, if 𝑠s is "abcaa" and you press Backspace instead of the last two letters, then the resulting text is "a".
Your task is to determine whether you can obtain the string 𝑡t, if you type the string 𝑠s and press "Backspace" instead of typing several (maybe zero) characters of 𝑠s.
Input
The first line contains a single integer 𝑞q (1≤𝑞≤1051≤q≤105) — the number of test cases.
The first line of each test case contains the string 𝑠s (1≤|𝑠|≤1051≤|s|≤105). Each character of 𝑠s is a lowercase English letter.
The second line of each test case contains the string 𝑡t (1≤|𝑡|≤1051≤|t|≤105). Each character of 𝑡t is a lowercase English letter.
It is guaranteed that the total number of characters in the strings over all test cases does not exceed 2⋅1052⋅105.
Output
For each test case, print "YES" if you can obtain the string 𝑡t by typing the string 𝑠s and replacing some characters with presses of "Backspace" button, or "NO" if you cannot.
You may print each letter in any case (YES, yes, Yes will all be recognized as positive answer, NO, no and nO will all be recognized as negative answer).
Example
input
Copy
4
ababa
ba
ababa
bb
aaa
aaaa
aababa
ababa
output
Copy
YES
NO
NO
YES
首先注意到,除了一开始就连续按退格以外,其他时候按退格会导致s中两个字母的消失。因此,如果s的长度和t的长度相差为奇数时,必然要在s刚开始时连续按奇数次退格。因此这种情况下不妨直接把s的第一个字符删掉,因此只需要考虑s的长度和t的长度相差为偶数的情况。对于这种情况,采取双指针法,外循环遍历t的每个字符,内循环找和这个字符相等的且合法(距离上一个被选择的位置间隔为偶数)的s的位置,如果t能被完全匹配则为YES,否则为NO。现在分析一下这种做法的正确性:假设\(|t|=1\),那么此时s中必然为奇数个字符(这样才能和t相差偶数个字符),设t的唯一一个字符为x,那么在s中如果x出现在开头,那么需要删除的为偶数个字符,此时一定可以;如果x前面有奇数个字符,那么x后面也有奇数个字符,这种情况实际上x会被跳过去(因为距离初始的pre距离为偶数)....剩余的情况用类似方法分析即可,总之这么做是对的~~~
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
string s, t;
cin >> s;
cin >> t;
if(s.size() < t.size()) {
puts("NO");
continue;
}
if((s.size() - t.size()) & 1) s = s.substr(1);
int p = 0, pre = -1;
int cnt = 0;
for(int i = 0; i < t.size(); i++) {
while(p < s.size() && (s[p] != t[i] || s[p] == t[i] && (p - pre) % 2 == 0)) p++;
if(p == s.size()) break;
cnt++;
pre = p;
}
if(cnt == t.size()) puts("YES");
else puts("NO");
}
return 0;
}
// 1
// aaabaaa
// aaab
// 1
// sswwdd
// swd
// 1
// baab
// aa
// 1
// baabb
// aa
// 1
// baaa
// b
// 1
// abaaa
// b
// 1
// abaa
// b