题意:
给出两个字符串s和t,对于s有两种操作,一种是将打印出来,另一种是删除
并且不会打印出
,问能否通过这两个操作得到t
思路:
首先我们可以考虑t已经从s中得到了,但是s还有部分需要打印,那么这部分长度一定是偶数,因为删除操作实际上是删除两个字符(一个是上一次打印出来的,另一个是当前要打印的),如果这部分长度不是偶数个,那么至少会多出一个字符。同样的,t中相邻的两个字符在s中需要间隔偶数个字符,否则也会至少多出一个字符。考虑贪心,从s的末尾往左找满足条件的字符。因为要找的满足条件的最后一个字符的奇偶性是固定的(我们只能从s的末尾开始删除偶数个字符),并且所有t中的字符在s中的位置的奇偶性都是固定的,如果我们不选择离s的末尾最近且等于t的最后一个字符的字符,我们就会找到下一个奇偶性相同且等于t的最后一个字符的位置,选择这两个字符本质上没有区别,而且如果选择离s的末尾更远的字符会将一些可能构成答案的字符略过,所以选择离s的末尾最近且满足条件的方案更优。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int t;
cin>>t;
while(t--)
{
string s, t;
cin>>s>>t;
int i=s.size()-1, j=t.size()-1;
while(i>=0 && j>=0)
{
if(s[i]==t[j]) i--, j--;
else i-=2;
}
if(j==-1) puts("YES");
else puts("NO");
}
return 0;
}
[cf] D. Say No to Palindromes
题意:
一个字符串如果不包含长度至少为2的回文串那么称这个字符串是beautiful的,你可以做的操作是能使一个不beautiful字符串的任意一个字符变为a,b,c中的一个,问给出一个字符串使它变成beautiful所需的最小操作次数。(注意:题目所给的字符串都只由a、b、c三个字符组成)
思路:
因为不能出现回文串,!=
&&
!=
&&
!=
,并且只有a、b、c三种字符,
就只能等于
, 所以每三个连续的字符,a、b、c都会出现并且只能出现一次。所以如果第一个和第二个字符确定了那么整个字符就确定了,所以可能的字符串就是由a、b、c的全排列,
也就是abcabc...、acbacb...、bacbac...、bcabca...、cabcab...、cbacba...。因为可能的beautiful字符串就只有这六种,所以可以直接用这六种字符串与给出的字符串比较,找出最小值。
这里用到了next_permutation函数,是用来求当前全排列的下一个全排列,next_permutation[first, last)如果没有下一个全排列组合就会返回false;否则返回true。
因为最后一个全排列组合会返回false,所以要用do while循环。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int n, m;
cin>>n>>m;
string s;
cin>>s;
vector<vector<int>> pr(6, vector<int> (n+1));
string t="abc";
int cur=0;
do{
for(int i=0; i<n; i++)
{
pr[cur][i+1]=pr[cur][i]+(s[i]!=t[i%3]);
}
cur++;
}while(next_permutation(t.begin(), t.end()));
while(m--)
{
int l, r;
cin>>l>>r;
int ans=n;
for(int i=0; i<6; i++)
{
ans=min(ans, pr[i][r]-pr[i][l-1]);
}
cout<<ans<<endl;
}
return 0;
}