ICPC Latin American Regional – 2017
Alan Curing is a famous sports programmer. He is the creator of the theoretical model of computation
known as the Alan Curing Machine (ACM). He’s most famous for creating his own computer for programming competitions: the Integrated Computer for Programming Contests (ICPC). This computer
has a specialized operating system with commands for submitting code and testing executables on sample inputs, an input generator, a wide display for debugging, and a very soft keyboard. However, as it
happens even to the best, Alan’s creation has a nasty bug. Every time Alan types a vowel on the ICPC,
the content of the current line is reversed.
The bug has been extremely hard to track down, so Alan has decided to accept the challenge and
use the computer as it is. He is currently training touch typing on the ICPC. For now, he is only typing
strings using lowercase letters, and no spaces. When Alan types a consonant, it is appended to the end
of the current line, as one would expect. When he types a vowel, however, the typed character is first
added to the end of the line, but right after that the whole line is reversed. For example, if the current
line has “imc” and Alan types “a” (a vowel), for a brief moment the line will become “imca”, but then
the bug kicks in and turns the line into “acmi”. If after that he types the consonants “c”, “p” and “c”,
in that order, the line becomes “acmicpc”.
When practicing, Alan first thinks of the text he wants to type, and then tries to come up with a
sequence of characters he can type in order to obtain that text. He is having trouble, however, since he
realized that he cannot obtain some texts at all (such as “ca”), and there are multiple ways of obtaining
other texts (as “ac”, which is obtained whether he types “ac” or “ca”). Help Alan in his training by
telling him in how many ways he can type each text he wishes to type. A way of typing a text T can
be encoded by a string W with |T| characters such that if the characters are typed on the ICPC in the
order they appear in W (i.e. W1, W2, . . . , W|T|) the final result is equal to T, considering ICPC’s known
bug. Two ways are considered different if they are encoded by different strings. The letters that trigger
the bug in the ICPC when typed are “a”, “e”, “i”, “o” and “u”.
Input
The input consists of a single line that contains a non-empty string T of at most 105
lowercase
letters, representing the text Alan wants to type on the ICPC.
Output
Output a single line with an integer representing the number of distinct ways Alan can type the
desired text T considering ICPC’s known bug.
Sample input 1
ac
Sample output 1
2
Sample input 2
ca
Sample output 2
0
Sample input 3
acmicpc
Sample output 3
3
题目大意:对于一个字符串,我们可以在它的尾部加入字符,如果加入的是元音字符(‘a’,‘e’,‘i’,‘u’,'o’等),那么该字符串将翻转,如果加入的是辅音字符(非元音字符),则没有变化,然后给出一个字符串,问我们有多少中方式去构造出这个字符串。
解题思路:我们可以通过上述规则构造一个字符串,反过来,我们也可以通过这个规则将整个字符串都删掉。然后我们来分析一下字符串的情况。对于一个字符串,总共有四种情况,列举出第一个元素和最后一个元素。
分别为:
元音-辅音:如果这个时候该字符串中只有一个元音字符,那么删去元音首部和尾部都可以,答案就等于这个字符串的长度。如果这个字符串中有至少两个元音字符,那么只能删掉后面的辅音字符。
辅音-辅音:这个字符串就只能删除末尾的辅音字符。
元音-元音:这时就只能删除前一个元音字符,然后翻转字符串。
辅音-元音:这个字符串是不合法的,即不可能构造得到这个字符串,答案为0。
然后我们就一直模拟这个过程就可以啦。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <bitset>
using namespace std;
#define int long long
const int maxn = 1e5 + 7;
const int inf = ((1ll*1)<<50);
int sum[maxn];
string arr;
bool judge(int i)
{
if(arr[i]=='i' || arr[i]=='a' || arr[i]=='e' || arr[i]=='o' || arr[i]=='u')
return true;
return false;
}
signed main()
{
cin >> arr;
for (int i = 0; arr[i] != '\0';i++){
sum[i + 1] = sum[i];
if(arr[i]=='i' || arr[i]=='a' || arr[i]=='e' || arr[i]=='o' || arr[i]=='u'){
sum[i + 1]++;
}
}
int head = 0, tail = arr.size() - 1;
int ans = 0, flag = 0;//flag==1 表示从头部删(翻转次数为奇数) flag==0 表示从尾部删(翻转次数为偶数)
while(head<tail){
if(judge(head) && judge(tail)){//都是元音
if(!flag)
head++;//如果是从尾部删除,删除前一个元音
else
tail--;//如果是从头部开始删除,删除尾部的元音
flag ^= 1;//翻转字符串
}
else if(judge(head) && !judge(tail)){//元音-辅音
if(flag){//如果从头部开始删,则是不合法字符串,跳出循环
break;
}
//从尾部开始删
if(sum[tail+1]-sum[head]>=2)//如果有至少两个元音字符
tail--;//删除末尾的辅音
else{
ans += tail-head+1;//如果只有一个元音字符,那么删除末尾的元音字符和辅音字符就都可以 所以可以直接返回答案
break;
}
//flag ^= 1;
}
else if(!judge(head) && !judge(tail)){//辅音-辅音
//都是辅音 那么就按照规则删除
if(flag)
head++;
else
tail--;
if(sum[tail+1]-sum[head]==0){//如果没有元音了,那么就只有一种方式,答案++
ans++;
break;
}
}
else{//辅音-元音
if(!flag)//如果从尾部开始删,则是不合法字符串,跳出循环
break;
if(sum[tail+1]-sum[head]>=2){如果有至少两个元音字符
head++;//删除头部的辅音
}
else{
ans += tail - head + 1;//如果只有一个元音字符,那么删除末尾的元音字符和辅音字符就都可以 所以可以直接返回答案(同上)
break;
}
//flag ^= 1;
}
}
if(head==tail)//如果可以删除完,答案++
ans++;
cout << ans << endl;
}