题意:电脑坏了,键入时,如果输入元音那么整个字符串会翻转,如果输入辅音是正常的。给一个字符串s,问有多少种输入可以得到它。
思路:如果可以照着它的规则,可以把该串删除到只剩一个字符,删除的方式反过来就成了得到它的一种方式。
-
首尾是辅音+元音,是一定不合法的。
-
首尾是元音+元音,那么删除首位置的元音,并翻转整个字符串。
-
首尾是辅音+辅音,那么删除末尾置的辅音。
-
首尾是元音+辅音,有两种。(1)删除末尾辅音;(2)删除首位置的元音,并翻转整个字符串。那么就会变成第一个字母是辅音的情况,这个时候如果字符串中还存在元音,那么就一定会得到不合法的情况1。否则就会得到一个全是辅音的字符串,得到该字符串有一种方式,于是ans++ 【也就是说虽然情况4有两个分支,但是其中一个分支的答案是确定的,我们只需要继续往下跑情况4的(1)即可】
开始用的string,最开始用的递归,MLE了。后来线性的,每次都翻转,T了。再后来问了学长改了双端队列,只需要用一个标记变量记录是否翻转即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define MID (l + r ) >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid + 1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 5;
bool judge(char ch)
{
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
int main()
{
string str;
while(cin >> str)
{
int aeiou = 0;
deque<char>dq;
for(int i = 0; i < str.length(); i ++ )
{
dq.push_back(str[i]);
if(judge(str[i]))
aeiou ++;
}
bool chge = false;
int ans = 0;
bool st, ed;
while(dq.size() > 1)
{
if(!chge)
{ st = judge(*dq.begin()); ed = judge(*dq.rbegin()); }
else
{ ed = judge(*dq.begin()); st = judge(*dq.rbegin()); }
if(!st && ed)//辅音+元音
break;
else if(st && ed)//元音+元音//删第一个元音并翻转
{
//删除第一个元音
if(!chge)//正序
dq.pop_front();
else
dq.pop_back();
//翻转
chge = !chge;
aeiou -- ;
}
else if(st && !ed)//元音+辅音
{
//还有两个及两个以上的元音,如果删除元音再翻转那一定就会到辅音+元音的情况,不合法
if(aeiou == 1)//如果只有这一个元音了,那么翻转之后删除元音,串中只剩辅音,那么就只有一种情况
ans ++;
//删除末尾辅音
if(!chge)
dq.pop_back();
else
dq.pop_front();
}
else if(!st && !ed)
{
//删除末尾辅音
if(!chge)
dq.pop_back();
else
dq.pop_front();
}
}
if(dq.size() == 1)
ans ++;
cout << ans << endl;
}
return 0;
}
/*
* acmicpc
*/