题意:
给你一个长度不大于1e6的字符串,由'a'-'z'或‘?’组成,且‘?’可转化为任意小写字母。和两个数x,y。
现在有两个条件:
-
字符串中存在任意一个长度为x的子串均为元音,或存在任意一个长度为y的子串均为子串。
-
字符串中所有的任意一个长度为x的子串不都是元音,且存在任意一个长度为y的子串不都是辅音。
如果同时满足条件(1)(2),则输出SURPRISE;
如果只满足(1),则输出(DISLIKE);
如果只满足(2),则输出(LIKE)。
思路
对于方案(1)
我们遍历一遍整个字符串,在‘?’的条件下,默认将元音和辅音的连续数都+1,并记录最大值判断即可。
对于方案(2)
首先我们可以判断,因为要求任意一个连续的元音/辅音小于x/y,因此我们考虑要使得他们连续的尽可能小。
因此我们考虑用dp对此进行维护。我们设dp[i][0/1],(0代表元音,1代表辅音)为位于第i号的结点时最小的连续的元音/辅音的个数。
对于某个位置的字符倘若为元音,倘若之前的状态为连续元音,则此需要将连续元音的数量+1;而倘若之前的状态为连续辅音,则此时需要将连续元音的数量重新置为1。
对于某个位置的字符为辅音的情况同理。
而对于某个位置为‘?’的情况如果之前的状态为连续的元音,则此时可以将辅音清零;如果之前的状态为连续的辅音,则此时可以将元音清零。之后只需要不断维护他们的最小值即可。倘若发现在某一个状态下,连续元音数超过x,连续辅音数超过y,则证明不满足条件(2)。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N =1e6+10;
const int M=1000000007;
int n,m,k;
int TT=1;
int dp[N][3];
bool judge(char c){
if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u')
return 1;
else return 0;
}
void slove()
{
string s;cin>>s;
n=s.length();
int a, b; cin>>a>>b;
string ans;
int flag=0;
int cnt1=0,cnt2=0;
for(int i=0;i<n;i++){
if(s[i]=='?'){
cnt1++,cnt2++;
}else{
if(judge(s[i])) cnt1++,cnt2=0;
else cnt2++,cnt1=0;
}
if(cnt1>=a || cnt2>=b){
flag=1;
break;
}
}
int flag2=1;
memset(dp,0x3f,sizeof dp);
dp[0][0]=dp[0][1]=0;
for(int i=1;i<=n;i++){
if(s[i-1]=='?'){
if(dp[i-1][0]<a) {
dp[i][0]=dp[i-1][0]+1;
dp[i][1]=1;
}
if(dp[i-1][1]<b){
dp[i][1]=min(dp[i][1],dp[i-1][1]+1);
dp[i][0]=1;
}
}else{
if(judge(s[i-1])){
dp[i][0]=dp[i-1][0]+1;
if(dp[i-1][1]<b) dp[i][0]=1;
}
else{
dp[i][1]=dp[i-1][1]+1;
if(dp[i-1][0]<a) dp[i][1]=1;
}
}
if(dp[i][0]>=a&&dp[i][1]>=b){
flag2=0;
break;
}
}
//cout<<flag<<" "<<flag2<<endl;
if(flag &&flag2) ans="SURPRISE";
if(flag && flag2==0) ans="DISLIKE";
if(flag==0 &&flag2) ans="LIKE";
cout<<"Case #"<<TT++<<": "<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
slove();
return 0;
}
————————————————
版权声明:本文为CSDN博主「Chen_Jr_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39453270/article/details/83831968