顽皮的字母
大家都知道有26个英文字母,abcdef…。由这些字母组成了一个字符串,但是,由于这些字母日久生情,有一些字母挨在一起的时候就会一起跑走玩耍。我们对26个字母编号1~26,就是说1对应a,…,26对应z,第i个字母和第i+1个字母相互有好感,挨在一起会跑开,i为1~26里面的奇数,跑开之后空位由后面的字母补上。现在问题来了,输入一个长度为n(n<10^5)的字符串,这个字符串包含挨在一起的情况比如ab挨在一起,问最后剩下的字符串是什么。
Input
第1行为数据组数T(T<=100)。
第2行到第T+1行为输入字符串,每行一个字符串。
保证输入全为英文小写字母。
Output
对于每个字符串,输出一行最后剩下的字符串。如果最后所有的字母都跑开了输出“sad!”,不包括引号。
Sample Input
2 ababababc abacda
Sample Output
c aa
解析:由于这个特殊的要求,如果用数组来回扫的话,肯定是超时了。所以我们可以用到栈,这样每个元素只进栈一次,时间就能达到O(n)的。具体实现方法如下:
先把第一个字符入栈,再把剩下的n-1个字符入栈, 每次入栈的时候都判断当前字符和栈顶元素是否满足跑走的条件:即两个字符中的较小的那个在字符表中的位置是奇数,且
两个字符在字母表中位置相邻。如果满足的话,就将栈顶元素出栈;否则,就将该字符入栈。然后重复上述操作,直到将剩下的n-1个字符全部扫一遍为止,最后在栈里面剩的就是剩下的字符串,不过直接弹出的话是倒序的,要调整一下顺序。
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; #define INF 0x7fffffff #define LL long long #define LLL(a, b) a<<b #define RRR(a, b) a>>b #define MID(a, b) a+(b-a)/2 const int maxn = 1000 + 10; int main(){ #ifdef sxk freopen("in.txt", "r", stdin); #endif // sxk int n; string s; scanf("%d", &n); while(n--){ char p[100005]; int foo = 0; cin >> s; int len = s.size(); for(int i=0; i<len; i++){ if(foo && min(p[foo-1] - 'a', s[i] - 'a') % 2 == 0 && abs(p[foo-1] - s[i]) == 1) foo --; //满足跑走的条件 else p[foo++] = s[i]; //不满足条件,字符入栈 } if(!foo) printf("sad!"); for(int i=0; i<foo; i++) cout << p[i]; cout << endl; } return 0; }
时间: 2024-11-03 03:29:27