【牛客网】最后一个字符
题目描述
正在挑战一个CrackMe的你,把需要填写的前面几位密码都正确猜出了,可是这最后一位密码,好像藏得有点深。CrackMe的作者还挑衅般的在里面藏了个.tar.gz文件,解压缩出来,里面写道 你要的最后一个字符就在下面这个字符串里,这个字符是下面整个字符串中第一个只出现一次的字符。(比如,串是abaccdeff,那么正确字符就是b了) 然而下面给出来的字符串好像太长太长了,单靠人力完全无法找出来。 于是,你需要写一个程序代劳了。输入文件体积较大,请使用一些快速的输入输出手段,不推荐使用cin/cout,对Java并不推荐使用Scanner直接读写。输入描述:
第一行,一个正整数T(T≤20) ,表示输入数据组数。
之后T行,每行一个字符串S。( 1≤S 的长度≤1000000 ,保证字符串中出现的字符的ASCII码在[0x21,0x7F)范围内,即均为可显示的非空白符,同时保证一定有解)输出描述:
一共T 行,每行一个字符C ,表示所给的相应字符串中第一个只出现一次的字符。输入例子:
2 abaccdeff testonline输出例子:
b
s
首先,不用cin/cout,当然采用scanf函数了。由于已知字符范围,可以以hash的方法建立一个count数组,遍历一遍字符串,找到每个字符出现的次数。再对字符串进行第二次遍历,找到第一个只出现一次的字符。
#include <string> #include<iostream> #include<vector> #include<algorithm> #include <stdlib.h> #include <stdio.h> #define MAX 100000 using namespace std; int main() { int T; cin >> T; char str[1000000]; string s; for (int i = 0; i < T; i++) { scanf("%s", str); s = str; //cin >> s; int n = 0x7F - 0x21; int count[94]; for (int j = 0; j < n; j++) count[j] = 0; for (int j = 0; j < s.length(); j++) { count[s[j] - 0x21]++; } for (int j = 0; j < s.length(); j++) if (count[s[j] - 0x21] == 1) { cout << s[j] << endl; break; } } return 0; }
注意点:
一、关于scanf
在VS 2013 中编译scanf 函数,编译时便会提示如下错误:
error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. |
原因是Visual C++ 2012 使用了更加安全的 run-time library routines 。新的Security CRT functions(就是那些带有“_s”后缀的函数),解决方案可以参考:http://www.cnblogs.com/gb2013/archive/2013/03/05/SecurityEnhancementsInTheCRT.html。
另外,下面的代码是无法将字符串读入s的,需使用字符数组,在拷贝到string类型的变量中。
string s;
scanf("%s",&s);