给定一个只包含下划线和大写字母的字符串,将下划线全部换成大写字母,问有多少种填法能使这个字符串满足以下三种要求:
- 不包含三个及以上连续的元音字母;
- 不包含三个及以上连续的辅音字母;
- 至少包含一个大写字母 L。
元音字母仅包含A,E,I,O,U,其他的字母都是辅音字母。
输入格式:
输入的一行给出一行字符串S;
∣S∣≤100
题目保证最多含有10个下划线,并且只会出现大写字母和下划线。
输出格式:
输出一个整数——表示方案数。
输入样例:
L_V
输出样例:
5
输入样例:
JA_BU_K_A
输出样例:
485
解题思路:
一开始拿到题目的时候是懵比的,想了好久,一开始的思路是在每个下划线上都放入一个合适的元音字母或者辅音字母,同时计录个数,最后全部放完之后判断原本字符串是否有‘L’的存在,如果不存在,辅音的个数要-1(但是如果连续遇到好多的连续下划线就会导致无法仿制,只能去一步步地尝试)。
因此我们倒不如直接尝试,(反正最多也就10个下划线)。用一个新的字符串来记录,所有的元音字母全部变为1,所有的‘L‘全部变成0,所有的除'L'的辅音字母全部变成2(这一步是为了最后全部放完之后字符串的合法性),加元音时,总数*5,加辅音时,总数*20,加’L‘时,不进行变化。最后合法了,总个数加上当前的个数就是正解。
下面是ac代码:
#include<bits/stdc++.h>
using namespace std;
string s;
long long ans;
int f=0;
string ss="";
void dfs(int tep,long long sum){
if(tep==s.size()){
int a=ss.find("0");
if(a==-1){
return ;
}
int f=0;
for(int i=1;i<ss.size()-1;i++){
if(ss[i]=='1'){
if(ss[i-1]=='1' && ss[i+1]=='1'){
f=1;
break;
}
}
if(ss[i]=='2' || ss[i]=='0'){
if(ss[i-1]=='0' || ss[i-1]=='2'){
if(ss[i+1]=='0' || ss[i+1]=='2'){
f=1;
break;
}
}
}
}
if(!f){
ans+=sum;
}
return ;
}
if(s[tep]=='A' || s[tep]=='E' || s[tep]=='I' || s[tep]=='O' || s[tep]=='U'){
ss+="1";
dfs(tep+1,sum);
ss.pop_back();
}else if(s[tep]=='_'){
ss+="1";
dfs(tep+1,sum*5);
ss.pop_back();
ss+="2";
dfs(tep+1,sum*20);
ss.pop_back();
ss+="0";
dfs(tep+1,sum);
ss.pop_back();
}else if(s[tep]=='L'){
ss+="0";
dfs(tep+1,sum);
ss.pop_back();
}else{
ss+="2";
dfs(tep+1,sum);
ss.pop_back();
}
}
void solve(){
cin>>s;
f=0;
ans=0;
dfs(0,1);
cout<<ans<<endl;
}
int main(){
int t=1;
while(t--){
solve();
}
return 0;
}