バランスの取れた文字列(シミュレーション+ディスカッション)

ここに画像の説明を挿入ここに画像の説明を挿入ここに画像の説明を挿入ここに画像の説明を挿入
質問の意味:主文字列が与えられた場合、与えられた主文字列にすべての偶数長の連続部分文字列を形成するように依頼し、すべての連続部分文字列の母音の数は子音の数に等しくなります。質問の構造はこれを満たします。全部ありますか?その中には、a、e、i、o、u、y、20種類の子音の6種類の母音があります。母音や子音で埋めることができます。

実際、この質問は読書のテストです。当時、競技会はこの質問に注意を払っていませんでした。補足されたことが判明したとき、これはHよりもはるかに簡単であることに気付きました。これは直接シミュレーションです。質問の要件によれば、難しいことではありません。質問で言及されているすべての偶数の長さを見つけるには、最小の偶数の長さは2です。したがって、隣接する文字の1つが母音で、もう1つが子音であることを確認するだけで済みます。
分類して説明しましょう。次のとおりです。
ここに画像の説明を挿入
赤い円は形成できないことを示しているので、0を出力します
。1つがすべてであることに注意してください。メインの文字列は奇数と偶数に分けられます。
たとえばここに画像の説明を挿入
、残りのケースは列挙するだけで済みます。
子音は母音だけを置くので、子音は母音だけを置くので、列挙してから最後にもう一度確認し
ます。
ACコード:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll QP(ll x,ll n){
    
    
	ll res=1;
	while(n){
    
    
		  if(n&1){
    
     
		    res=res*x;
		  }
		  x*=x;
		  n>>=1;
	}
	return res;
}
bool vowel(char c){
    
    
	return c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||c=='y';
}
int main(){
    
    
	int T;
	scanf("%d",&T);
	int g=1;
	while(T--){
    
    
       string s;
       cin>>s;
        ll num=0;
        for(int i=0;i<s.length();i++)if(s[i]=='?')num++;
        if(num==s.length()){
    
    //如果说全是? 
        	if(num%2==0){
    
    
        		printf("String #%d: %lld\n",g++,2*QP(20,num/2)*QP(6,num/2));
			}else{
    
    
				printf("String #%d: %lld\n",g++,QP(20,num/2+1)*QP(6,num/2)+QP(20,num/2)*QP(6,num/2+1));
			}
		}else{
    
    
			ll ans=1;
			int f=0;
			for(int i=1;i<s.length()-1;i++){
    
    
				if(s[i]=='?'){
    
    
				if(s[i-1]!='?'&&s[i+1]!='?'){
    
    
				  if((vowel(s[i-1])&&!vowel(s[i+1]))||(!vowel(s[i-1])&&vowel(s[i+1]))){
    
    //前是元音,后面是辅音或者前面是辅音,后面是元音,这种情况直接不成立了 
				  	 f=1;break;
				  }
			     }
			   }else{
    
    
			   	  if(s[i-1]!='?'){
    
    //相邻两个已知的情况下 如果相邻是元音或者为辅音,那么肯定答案就是0了
			   	  	   if((vowel(s[i])&&vowel(s[i-1]))||(!vowel(s[i])&&!vowel(s[i-1])))f=1;break;
					 }else if(s[i+1]!='?'){
    
    
					 	 if((vowel(s[i])&&vowel(s[i+1]))||(!vowel(s[i])&&!vowel(s[i+1])))f=1;break;
					 }
			   }
			}
			if(f) printf("String #%d: 0\n",g++);
			else {
    
    
				int index;
				for(int i=0;i<s.length();i++){
    
    
					   if(s[i]<='z'&&s[i]>='a'){
    
    //找到一个字母 
					   	  index=i;break;
					   }
				}
					//左边
					for(int i=index-1;i>=0;i--){
    
    
						  if(vowel(s[i+1])&&s[i]=='?'){
    
    
						  	  ans*=20;s[i]='z';
						  }else if(!vowel(s[i+1])&&s[i]=='?'){
    
    
						  	  ans*=6;s[i]='a';
						  }
					} 
					//右边
					for(int i=index+1;i<s.length();i++){
    
    
						   if(vowel(s[i-1])&&s[i]=='?'){
    
    
						  	  ans*=20;s[i]='z';//z表示辅音,表示这个位置已经放了一个辅音了
						  }else if(!vowel(s[i-1])&&s[i]=='?'){
    
    
						  	  ans*=6;s[i]='a';//a表示元音,表示这个位置已经放了一个元音了
						 
						  }
					}
					int f2=0;
				for(int i=0;i<s.length()-1;i++){
    
    
					  if((vowel(s[i])&&vowel(s[i+1]))||(!vowel(s[i])&&!vowel(s[i+1]))){
    
    //检查相邻的是不是都是元音或者辅音
					  	  f2=1;break;
					  }
				}
				if(f2)  printf("String #%d: 0\n",g++);
				else  printf("String #%d: %lld\n",g++,ans);
			}
		}
		puts("");
	}
	return 0;
} 

おすすめ

転載: blog.csdn.net/qq_44555205/article/details/104558719