1、HDU 5688 Problem D
解题思路:
对字符串按照 ASCII 值排序后 用 map 存
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const int INF = 0x7fffffff;
const int maxn = 40 + 10;
char name[maxn];
int vis[30][30][30];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int N;
scanf("%d", &N);
map<string, int> Map;
for (int i = 0; i < N; ++i) {
scanf("%s", name);
int len = strlen(name);
sort(name, name+len);
printf("%d\n", Map[name]);
Map[name] += 1;
}
return 0;
}
2、CodeForces_2A Winner
题意:
给出选手姓名和分数(可能为负数)
求最后得分最高且第一个达到这个分数的人
解题思路:
先求出每个人的最后得分和最高分数
然后再判断最后得分最高的人哪个先获得这个分数(可能大于这个分数)
用 map 模拟
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const double eps = 1e-8;
const int INF = 0x7fffffff;
const int maxn = 50;
char s[maxn];
map<string, int> M, M_t;
vector<string> V_name;
vector<int> V_score;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int n;
scanf("%d", &n);
int t;
for (int i = 0; i < n; ++i) {
scanf("%s%d", s, &t);
V_name.push_back(s);
V_score.push_back(t);
M[s] += t;
}
int Max = -1;
map<string, int>::iterator itr;
for (itr = M.begin(); itr != M.end(); ++itr) {
if (itr->second > Max) {
Max = itr->second;
}
}
for (int i = 0; i < n; ++i) {
M_t[V_name[i]] += V_score[i];
if (M_t[V_name[i]] >= Max && M[V_name[i]] == Max) {
cout << V_name[i] << endl;
break;
}
}
return 0;
}
3、HDU 1004 Let the Balloon Rise
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 15 + 10;
char color[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int N;
while (scanf("%d", &N) != EOF && N != 0) {
map<string, int> Map;
for (int i = 1; i <= N; ++i) {
scanf("%s", color);
Map[color] += 1;
}
map<string, int>::iterator itr;
int Max = -1;
for (itr = Map.begin(); itr != Map.end(); ++itr) {
if (itr->second > Max) {
Max = itr->second;
}
}
for (itr = Map.begin(); itr != Map.end(); ++itr) {
if (itr->second == Max) {
cout << itr->first << endl;
break;
}
}
}
return 0;
}
4、字符串操作
-
描述
-
给定n个字符串(从1开始编号),每个字符串中的字符位置从0开始编号,长度为1-500,现有如下若干操作:
- copy N X L:取出第N个字符串第X个字符开始的长度为L的字符串。
- add S1 S2:判断S1,S2是否为0-99999之间的整数,若是则将其转化为整数做加法,若不是,则作字符串加法,返回的值为一字符串。
- find S N:在第N个字符串中从左开始找寻S字符串,返回其第一次出现的位置,若没有找到,返回字符串的长度。
- rfind S N:在第N个字符串中从右开始找寻S字符串,返回其第一次出现的位置,若没有找到,返回字符串的长度。
- insert S N X:在第N个字符串的第X个字符位置中插入S字符串。
- reset S N:将第N个字符串变为S。
- print N:打印输出第N个字符串。
- printall:打印输出所有字符串。
- over:结束操作。
其中N,X,L可由find与rfind操作表达式构成,S,S1,S2可由copy与add操作表达式构成。
输入
-
第一行为一个整数n(n在1-20之间)
接下来n行为n个字符串,字符串不包含空格及操作命令等。
接下来若干行为一系列操作,直到over结束。
输出
-
根据操作提示输出对应字符串。
样例输入
-
3 329strjvc Opadfk48 Ifjoqwoqejr insert copy 1 find 2 1 2 2 2 print 2 reset add copy 1 find 3 1 3 copy 2 find 2 2 2 3 print 3 insert a 3 2 printall over
样例输出
-
Op29adfk48 358 329strjvc Op29adfk48 35a8
提示
-
推荐使用string类中的相关操作函数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
using namespace std;
#define DEBUG printf("DEBUG\n")
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 30;
int n;
string s[30];
string cmd;
string cmd_t;
string S;
int N, X, L;
string Get_S(void);
int Get_X(void);
string Copy(void);
string Add(void);
int Find(void);
int Rfind(void);
int Judge(string key);
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
cin >> s[i];
}
while (cin >> cmd && cmd != "over") {
if (cmd == "insert") {
S = Get_S();
scanf("%d", &N);
X = Get_X();
s[N].insert(X, S);
} else if (cmd == "reset") {
S = Get_S();
scanf("%d", &N);
s[N] = S;
} else if (cmd == "print") {
scanf("%d", &N);
cout << s[N] << endl;
} else {
for (int i = 1; i <= n; ++i) {
cout << s[i] << endl;
}
}
}
return 0;
}
string Get_S(void)
{
cin >> cmd_t;
if (cmd_t == "copy") {
return Copy();
} else if (cmd_t == "add") {
return Add();
} else {
return cmd_t;
}
}
int Get_X(void)
{
cin >> cmd_t;
if (cmd_t == "find") {
return Find();
} else if (cmd_t == "rfind") {
return Rfind();
} else {
int t = 0;
int len = cmd_t.length();
for (int i = 0; i < len; ++i) {
t = t*10 + cmd_t[i] - '0';
}
return t;
}
}
string Copy(void)
{
string ret ("");
scanf("%d", &N);
X = Get_X();
L = Get_X();
for (int i = X; i < X+L; ++i) {
ret += s[N][i];
}
return ret;
}
string Add(void)
{
string S1, S2;
S1 = Get_S();
S2 = Get_S();
int j1 = Judge(S1), j2 = Judge(S2);
if (j1 != -1 && j2 != -1) {
j1 += j2;
char t[10];
sprintf(t, "%d", j1);
return t;
}
return (S1+S2);
}
int Find(void)
{
string t = Get_S();
scanf("%d", &N);
size_t pos = s[N].find(t, 0);
if (pos != string::npos) {
return pos;
}
return t.length();
}
int Rfind(void)
{
string t = Get_S();
scanf("%d", &N);
int len = s[N].length();
size_t pos = s[N].rfind(t, len-1);
if (pos != string::npos) {
return pos;
}
return t.length();
}
int Judge(string key)
{
int len = key.length();
int ret = 0;
for (int i = 0; i < len; ++i) {
if (!isdigit(key[i])) {
return -1;
}
ret = ret*10 + key[i] - '0';
}
if (ret <= 99999) {
return ret;
}
return -1;
}
5、最短前缀
-
描述
-
一个字符串的前缀是从该字符串的第一个字符起始的一个子串。例如 "carbon"的字串是: "c", "ca", "car", "carb", "carbo", 和 "carbon"。注意到这里我们不认为空串是字串, 但是每个非空串是它自身的字串. 我们现在希望能用前缀来缩略的表示单词。例如, "carbohydrate" 通常用"carb"来缩略表示. 现在给你一组单词, 要求你找到唯一标识每个单词的最短前缀
在下面的例子中,"carbohydrate" 能被缩略成"carboh", 但是不能被缩略成"carbo" (或其余更短的前缀) 因为已经有一个单词用"carbo"开始
一个精确匹配会覆盖一个前缀匹配,例如,前缀"car"精确匹配单词"car". 因此 "car" 是 "car"的缩略语是没有二义性的 , “car”不会被当成"carriage"或者任何在列表中以"car"开始的单词.
输入
- 输入包括至少2行,至多1000行. 每行包括一个以小写字母组成的单词,单词长度至少是1,至多是20. 输出
- 输出的行数与输入的行数相同。每行输出由相应行输入的单词开始,后面跟着一个空格接下来是相应单词的没有二义性的最短前缀标识符。 样例输入
-
carbohydrate cart carburetor caramel caribou carbonic cartilage carbon carriage carton car carbonate
样例输出
-
carbohydrate carboh cart cart carburetor carbu caramel cara caribou cari carbonic carboni cartilage carti carbon carbon carriage carr carton carto car car carbonate carbona
来源
- 翻译自Rocky Mountain 2004
纯暴力解法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
map<string, int> Map;
char s[1010][30];
char t[30];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
int Count = 0;
while (gets(t)) {
int len = strlen(t);
for (int i = 1; i <= len; ++i) {
string s_t = "";
for (int j = 0; j < i; ++j) {
s_t += t[j];
}
Map[s_t] += 1;
}
strcpy(s[Count], t);
++Count;
}
for (int i = 0; i < Count; ++i) {
printf("%s ", s[i]);
int len = strlen(s[i]);
bool flag = false;
for (int j = 1; j <= len; ++j) {
string s_t = "";
for (int k = 0; k < j; ++k) {
s_t += s[i][k];
}
if (Map[s_t] == 1) {
flag = true;
cout << s_t << endl;
break;
}
}
if (!flag) {
printf("%s\n", s[i]);
}
}
return 0;
}