团队程序设计天梯赛-3.12排位赛总结

7-1 12-24小时制 (10 分)

题目

编写一个程序,要求用户输入24小时制的时间,然后显示12小时制的时间。

输入格式:
输入在一行中给出带有中间的:符号(半角的冒号)的24小时制的时间,如12:34表示12点34分。当小时或分钟数小于10时,均没有前导的零,如5:6表示5点零6分。

提示:在scanf的格式字符串中加入:,让scanf来处理这个冒号。

输出格式:
在一行中输出这个时间对应的12小时制的时间,数字部分格式与输入的相同,然后跟上空格,再跟上表示上午的字符串AM或表示下午的字符串PM。如5:6 PM表示下午5点零6分。注意,在英文的习惯中,中午12点被认为是下午,所以24小时制的12:00就是12小时制的12:0 PM;而0点被认为是第二天的时间,所以是0:0 AM。

输入样例:

21:11

输出样例:

9:11 PM

思路

  • 注意24:00,0:00,12:00的特殊情况的处理
  • 当时写的时候用的是取模,判断条件时忽略了24:00-1:00,0:00-1:00,12:00-13:00的处理,做到后面才发现
  • 参考代码就很简洁

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
	int h, m;
	scanf("%d:%d", &h, &m);
	string s = h<12 ? "AM" : "PM";
	if(h>=13) h -= 12;
	printf("%d:%d ", h, m);
	cout << s;
	return 0;
}

7-2 有理数加法 (10 分)

题目

本题要求编写程序,计算两个有理数的和。

输入格式:
输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:
在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。

输入样例1:

1/3 1/6

输出样例1:

1/2

输入样例2:

4/3 2/3

输出样例2:

2

知识点

  • __gcd(x,y):求x,y的最大公约数

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
	int a1, a2, b1, b2;
	scanf("%d/%d %d/%d", &a1, &a2, &b1, &b2);
	int x = a2*b2/__gcd(a2, b2);//__gcd:最大公约数, x:通分后的分母
	int a = a1*(x/a2) + b1*(x/b2);//通分后的分子之和
	int b = __gcd(a, x); //分子分母的最大公约数
	if(b==x) cout << a/x;
	else printf("%d/%d", a/b, x/b);
	return 0;
}

7-3 不变初心数 (15 分)

题目

不变初心数是指这样一种特别的数,它分别乘 2、3、4、5、6、7、8、9 时,所得乘积各位数之和却不变。例如 18 就是这样的数:18 的 2 倍是 36,3+6=9;18 的 3 倍是 54,5+4=9;…… 18 的 9 倍是 162,1+6+2=9。对于 18 而言,9 就是它的初心。本题要求你判断任一个给定的数是否有不变的初心。

输入格式:
输入在第一行中给出一个正整数 N(≤ 100)。随后 N 行,每行给出一个不超过 10
5
的正整数。

输出格式:
对每个给定的数字,如果它有不变的初心,就在一行中输出它的初心;否则输出 NO。

输入样例:

4
18
256
99792
88672

输出样例:

9
NO
36
NO

知识点

  • 对数的每一位进行求和
  • 参考代码中用的是求出每一位数后进行求和:
int sum(long long x) {
	int res = 0;
	while(x) {
		res += x%10;
		x /= 10;
	}
	return res;
}
  • 我当时是把数字转换为字符串后对每一位进行求和
    – to_string():将数字转为字符串
bool judge(int num,int orgin){
	string s = to_string(num);
	int each=0;
	for(auto t:s){
		char c = t;
		each+=t-'0';
	}
	if(each == orgin){
		return true;
	}
	else return false;
}

代码一

#include<bits/stdc++.h>
using namespace std;
int sum(long long x) {
	int res = 0;
	while(x) {
		res += x%10;
		x /= 10;
	}
	return res;
}
int ju(long long x) {
	int res = sum(x*2);
	int i;
	for(i=3; i<=9; i++)
		if(sum(x*i)!=res) return -1;
	return res;
}
int main() {
	int n;
	cin >> n;
	while(n--) {
		int x;
		cin >> x;
		int res = ju(x);
		if(res==-1) cout << "NO\n";
		else cout << res << endl;
	}
	return 0;
}

代码二

#include <bits/stdc++.h>
using namespace std;
int a[8] = {2,3,4,5,6,7,8,9};
bool judge(int num,int orgin) {
	string s = to_string(num);
	int each=0;
	for(auto t:s) {
		char c = t;
		each+=t-'0';

	}
	if(each == orgin) {
		return true;
	} else return false;
}
int main() {
	int n;
	cin>>n;
	while(n--) {
		int num;
		cin>>num;
		bool flag = true;
		int orgin;
		int t = num*2;
		string s = to_string(t);
		int org = 0;
		for(auto t:s) {
			char c = t;
			org+=t-'0';
		}
		for(int i=1; i<8; i++) {
			int tmp = num*a[i];
			if(!judge(tmp,org)) {
				flag = false;
			}
		}
		if(flag == true) {
			cout<<org<<'\n';
		} else {
			cout<<"NO"<<'\n';
		}
	}
}

7-4 简单计算器 (15 分)

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
输入样例 1:

5
40 5 8 3 2
/ * - +

输出样例 1:

2

输入样例 2:

5
2 5 8 4 4
* / - +

输出样例 2:

ERROR: 5/0

知识点

模拟运算的过程即可,参考代码用的是数组模拟栈

代码

#include<iostream>
using namespace std;
int main() {
	int n;
	cin >> n;
	int a[1000];
	char b[1000];
	for(int i=0; i<n; i++) cin >> a[i];
	for(int i=1; i<n; i++) cin >> b[i];
	for(int i=n-1; i>0; i--) {
		if(b[i]=='+') a[i-1] = a[i-1]+a[i];
		else if(b[i]=='-') a[i-1] = a[i-1]-a[i];
		else if(b[i]=='*') a[i-1] = a[i-1]*a[i];
		else if(a[i]!=0) a[i-1] = a[i-1]/a[i];
		else {
			cout << "ERROR: " << a[i-1] << "/0";
			return 0;
		}
	}
	cout << a[0];
	return 0;
}

7-5 树种统计 (20 分)

题目

随着卫星成像技术的应用,自然资源研究机构可以识别每一棵树的种类。请编写程序帮助研究人员统计每种树的数量,计算每种树占总数的百分比。

输入格式:
输入首先给出正整数N(≤10
5
),随后N行,每行给出卫星观测到的一棵树的种类名称。种类名称由不超过30个英文字母和空格组成(大小写不区分)。

输出格式:
按字典序递增输出各种树的种类名称及其所占总数的百分比,其间以空格分隔,保留小数点后4位。

输入样例:

29
Red Alder
Ash
Aspen
Basswood
Ash
Beech
Yellow Birch
Ash
Cherry
Cottonwood
Ash
Cypress
Red Elm
Gum
Hackberry
White Oak
Hickory
Pecan
Hard Maple
White Oak
Soft Maple
Red Oak
Red Oak
White Oak
Poplan
Sassafras
Sycamore
Black Walnut
Willow

输出样例:

Ash 13.7931%
Aspen 3.4483%
Basswood 3.4483%
Beech 3.4483%
Black Walnut 3.4483%
Cherry 3.4483%
Cottonwood 3.4483%
Cypress 3.4483%
Gum 3.4483%
Hackberry 3.4483%
Hard Maple 3.4483%
Hickory 3.4483%
Pecan 3.4483%
Poplan 3.4483%
Red Alder 3.4483%
Red Elm 3.4483%
Red Oak 6.8966%
Sassafras 3.4483%
Soft Maple 3.4483%
Sycamore 3.4483%
White Oak 10.3448%
Willow 3.4483%
Yellow Birch 3.4483%

知识点

  • 用map<string,int>进行去重和保存数量
  • 注意含空格的字符串输入使用getline(cin,s)

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n;
	cin >> n;
	getchar();
	map<string, int> mp;
	for(int i=0; i<n; i++) {
		string s;
		getline(cin, s);
		mp[s]++;
	}
	for(auto x:mp) {
		cout << x.first;
		printf(" %.4f%%\n", 100.0*x.second/n);
	}
	return 0;
}

7-6 出租 (20 分)

题目

在这里插入图片描述
在这里插入图片描述
输入格式:
输入在一行中给出一个由11位数字组成的手机号码。

输出格式:
为输入的号码生成代码的前两行,其中arr中的数字必须按递减顺序给出。

输入样例:

18013820100

输出样例:

int[] arr = new int[]{8,3,2,1,0};
int[] index = new int[]{3,0,4,3,1,0,2,4,3,4,4

代码

#include<iostream>
#include<set>
#include<cstring>
using namespace std;
int main() {
	char str[11];
	int pos[10]; //pos[i]: 数字i所在的arr数组的下标
	set <int, greater<int>> s;
	cin >> str;
	int i;
	for(i=0; i<11; i++) s.insert(str[i]-48);//把字符插入到集合中
	int cnt = 0;
	cout << "int[] arr = new int[]{";
	for(auto data:s) { //取集合中的每一个元素
		cout << data;
		if(cnt!=s.size()-1) cout << ",";
		pos[data] = cnt++;//数字*i所在arr数组的下标
	}
	cout << "};" << endl;
	cout << "int[] index = new int[]{" << pos[str[0]-48];
	for(i=1; i<11; i++) cout << "," << pos[str[i]-48];
	cout << "};" << endl;
}

7-7 凯撒密码 (25 分)

题目

为了防止信息被别人轻易窃取,需要把电码明文通过加密方式变换成为密文。输入一个以回车符为结束标志的字符串(少于80个字符),再输入一个整数offset,用凯撒密码将其加密后输出。恺撒密码是一种简单的替换加密技术,将明文中的所有字母都在字母表上偏移offset位后被替换成密文,当offset大于零时,表示向后偏移;当offset小于零时,表示向前偏移。

输入格式:
输入第一行给出一个以回车结束的非空字符串(少于80个字符);第二行输入一个整数offset。

输出格式:
输出加密后的结果字符串。

输入样例1:

Hello Hangzhou
2

输出样例1:

Jgnnq Jcpibjqw

输入样例2:

a=x+y
-1

输出样例2:

z=w+x

注意点

  • 偏移量大于26时的处理
  • 偏移后超出字母表范围的处理

参考代码的思路

先求出字母表中各个字符进行偏移后对应的字符是什么,然后存入map中形成对应关系,然后结合该map对输入的字符串进行转换

知识点

  • isalpha():判断是否为字母(大写或小写)
  • 还有常用的如isalnum()(字母或数字),isupper()(是否为大写),islower()(是否为小写),toupper(),tolower(),isdight()(一个字符是否是十进制数字)等
  • <ctype.h>头文件详解

代码

#include<bits/stdc++.h>
using namespace std;
int main() {
	string s;
	int n;
	string a = "abcdefghijklmnopqrstuvwxyz";
	map<char, char> mp;
	getline(cin, s);
	cin >> n;
	if(n<0) {
		n = -n;
		reverse(a.begin(), a.end());
	}
	for(int i=0; i<=25; i++) {
		mp[a[i]] = a[(i+n)%26];
		mp[a[i]-32] = a[(i+n)%26]-32;
	}
	for(char x:s) {
		if(isalpha(x)) x = mp[x];
		cout << x;
	}
}

7-8 完全二叉搜索树 (25 分)

题目

一个无重复的非负整数序列,必定对应唯一的一棵形状为完全二叉树的二叉搜索树。本题就要求你输出这棵树的层序遍历序列。

输入格式:
首先第一行给出一个正整数 N(≤1000),随后第二行给出 N 个不重复的非负整数。数字间以空格分隔,所有数字不超过 2000。

输出格式:
在一行中输出这棵树的层序遍历序列。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

10
1 2 3 4 5 6 7 8 9 0

输出样例:

6 3 8 1 5 7 9 0 2 4

知识点

  • 完全二叉树的二叉搜索树的中序遍历是这些数字从小到大排序后的数列
  • “对层序中第t个数为根的子树进行中序遍历”,“层序的第t个数是中序的第num个数”
void dfs(int t) {
	//对层序中第t个数为根的子树进行中序遍历
	if(t>n) return;//t超出范围
	dfs(t*2);//遍历左子树
	level[t] = num++; //层序的第t个数是中序的第num个数
	dfs(t*2+1); //右子树
}

代码

#include<bits/stdc++.h>
using namespace std;
int num = 1, n;
int a[1001], level[1001];
void dfs(int t) {
	//对层序中第t个数为根的子树进行中序遍历
	if(t>n) return;//t超出范围
	dfs(t*2);//遍历左子树
	level[t] = num++; //层序的第t个数是中序的第num个数
	dfs(t*2+1); //右子树
}
int main() {
	cin >> n;
	for(int i=1; i<=n; i++) cin >> a[i];
	sort(a+1, a+n+1);
	dfs(1);
	for(int i=1; i<=n; i++) {
		if(i>1) cout << " ";
		cout << a[level[i]];
	}
}

7-9 旅游规划 (25 分)

题目

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

3 40

知识点

代码一(迪杰斯特拉)

#include<bits/stdc++.h>
using namespace std;
const int inf = 999999;
struct node {
	int len, fee;
};
node a[500][500];
int n, m, s, d;
int blen = inf, bfee = inf;
bool vis[500];
int len[500], fee[500];
void Dijkstra() {
	fill(len, len+n, inf);
	fill(fee, fee+n, inf);
	for(int i=0; i<n; i++)
		len[i] = a[s][i].len, fee[i] = a[s][i].fee;//初始化
	bool vis[500] = {0};
	vis[s] = 1;
	for(int i=1; i<n; i++) {
		int min = inf, minid;
		for(int j=0; j<n; j++)//找最小
			if(!vis[j] && len[j]<min) min = len[j], minid = j;
		if(minid==d) break;
		vis[minid] = 1;
		for(int j=0; j<n; j++) { //刷新其他
			if(!vis[j]) {
				if(min+a[minid][j].len < len[j]) {
					len[j] = min+a[minid][j].len;
					fee[j] = fee[minid]+a[minid][j].fee;
				} else if(min+a[minid][j].len==len[j] && fee[minid]+a[minid]
				          [j].fee<fee[j])
					fee[j] = fee[minid]+a[minid][j].fee;
			}
		}
	}
}
int main() {
	cin >> n >> m >> s >> d;
	for(int i=0; i<n; i++)
		for(int j=0; j<n; j++)
			a[i][j].len = inf;
	while(m--) {
		int x, y, z, w;
		cin >> x >> y >> z >> w;
		a[x][y] = a[y][x] = {z, w};
	}
	Dijkstra();
	cout << len[d] << " " << fee[d] << endl;
}

代码二(弗洛伊德算法)

#include "iostream"
#include "algorithm"
#include "cstring"
using namespace std;
int n, m, s, e, a[500][500], b[500][500];
int inf = 1000;
bool cmp(int aa, int bb) { return aa > bb; }
int main() {
  cin >> n >> m >> s >> e;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      a[i][j]=b[i][j]=inf;
  while (m--) {
    int u, v, l, w;
    cin >> u >> v >> l >> w;
    a[u][v] = l;
    a[v][u] = l;
    b[u][v] = w;
    b[v][u] = w;
 }/*
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++)
      cout << a[i][j] << ' ';
    cout << endl;
  }*/
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        if (a[i][k] + a[k][j] <= a[i][j]) {
          if(a[i][k] + a[k][j] == a[i][j])
            b[i][j] = min(b[i][j],b[i][k] + b[k][j]);
          else {
            a[i][j] = a[i][k] + a[k][j];
            b[i][j] = b[i][k] + b[k][j];
         }
       }
     }
  cout << a[s][e] << " " << b[s][e];
}

7-10 特殊堆栈 (25 分)

题目

堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 N 个元素,如果 N 是偶数,则中值定义为第 N/2 小元;若是奇数,则为第 (N+1)/2 小元。

输入格式:
输入的第一行是正整数 N(≤10
5
)。随后 N 行,每行给出一句指令,为以下 3 种之一:

Push key
Pop
PeekMedian
其中 key 是不超过 10
5
的正整数;Push 表示“入栈”;Pop 表示“出栈”;PeekMedian 表示“取中值”。

输出格式:
对每个 Push 操作,将 key 插入堆栈,无需输出;对每个 Pop 或 PeekMedian 操作,在一行中输出相应的返回值。若操作非法,则对应输出 Invalid。

输入样例:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

输出样例:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

思路

peek中位数时如果直接排序再找中位数,会超时。
所以每次push和pop的时候都维护数组中已有的数据使其有序

知识点

lower_bound():lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素,底层实现采用二分查找,效率高
以后遇到超时+需要查找的情况可考虑使用二分查找改进
二分查找相关函数:
upper_bound():用于在指定范围内查找大于目标值的第一个元素
lower_bound() 函数:用于在指定区域内查找不小于目标值的第一个元素。
equel_range() 函数:用于在指定范围内查找等于目标值的所有元素
binary_search() 函数:用于查找指定区域内是否包含某个目标元素。

代码

#include<bits/stdc++.h>
using namespace std;
vector<int> a, b;
vector<int>::iterator it;
int main() {
	int n;
	cin >> n;
	while(n--) {
		string s;
		cin >> s;
		switch(s[1]) {
			case 'u':
				int x;
				cin >> x;
				a.push_back(x);
				it = lower_bound(b.begin(), b.end(), x);
				b.insert(it, x);
				break;
			case 'o':
				if(a.size()==0) cout << "Invalid\n";
				else {
					cout << a.back() << endl;
					it = lower_bound(b.begin(), b.end(), a.back());
					a.pop_back();
					b.erase(it);
					
				}
				break;
			case 'e':
					if(a.size()==0) cout << "Invalid\n";
					else cout << b[(b.size()-1)/2] << endl;
		}
	}
	return 0;
}

7-11 肿瘤诊断 (25 分)

题目

在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环。给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积。

输入格式:
输入第一行给出4个正整数:M、N、L、T,其中M和N是每张切片的尺寸(即每张切片是一个M×N的像素矩阵。最大分辨率是1286×128);L(≤60)是切片的张数;T是一个整数阈值(若疑似肿瘤的连通体体积小于T,则该小块忽略不计)。

最后给出L张切片。每张用一个由0和1组成的M×N的矩阵表示,其中1表示疑似肿瘤的像素,0表示正常像素。由于切片厚度可以认为是一个常数,于是我们只要数连通体中1的个数就可以得到体积了。麻烦的是,可能存在多个肿瘤,这时我们只统计那些体积不小于T的。两个像素被认为是“连通的”,如果它们有一个共同的切面,如下图所示,所有6个红色的像素都与蓝色的像素连通。
在这里插入图片描述
输出格式:
在一行中输出肿瘤的总体积。

输入样例:

3 4 5 2
1 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0

输出样例:

26

思路

三维空间进行广搜。注意如果深搜可能空间出错。
有空再看吧…

代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
int mp[1300][130][66],num;
int dir[6][3] = {1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1};
int n,m,h,up,ans;
struct node {
	int x,y,z;
};
void bfs(int x,int y,int z){
	mp[x][y][z] = 0;
	num++;
	queue<node> q;
	q.push({x,y,z});
	while(!q.empty()) {
		auto t = q.front();
		int tx = t.x,ty = t.y,tz = t.z;
		q.pop();
		for(int i = 0; i < 6; i++) {
			x = tx+dir[i][0];
			y = ty+dir[i][1];
			z = tz+dir[i][2];
			if(x>=1&&x<=n&&y>=1&&y<=m&&z>=1&&z<=h&&mp[x][y][z]) {
				q.push({x,y,z});
				mp[x][y][z] = 0;
				num++;
			}
		}
	}
}
int main() {
	cin>>n>>m>>h>>up;
	for(int i = 1; i <= h; i++)
		for(int j = 1; j <= n; j++)
			for(int k = 1; k <= m; k++)
				cin>>mp[j][k][i];
	for(int i = 1; i <= h; i++)
		for(int j = 1; j <= n; j++)
			for(int k = 1; k <= m; k++)
				if(mp[j][k][i] == 1) {
					num = 0;
					bfs(j,k,i);
					if(num >= up)
						ans += num;
				}
	printf("%d\n",ans);
	return 0;
}

7-12 新浪微博热门话题 (30 分)

题目

新浪微博可以在发言中嵌入“话题”,即将发言中的话题文字写在一对“#”之间,就可以生成话题链接,点击链接可以看到有多少人在跟自己讨论相同或者相似的话题。新浪微博还会随时更新热门话题列表,并将最热门的话题放在醒目的位置推荐大家关注。

本题目要求实现一个简化的热门话题推荐功能,从大量英文(因为中文分词处理比较麻烦)微博中解析出话题,找出被最多条微博提到的话题。

输入格式:
输入说明:输入首先给出一个正整数N(≤10
5
),随后N行,每行给出一条英文微博,其长度不超过140个字符。任何包含在一对最近的#中的内容均被认为是一个话题,输入保证#成对出现。

输出格式:
第一行输出被最多条微博提到的话题,第二行输出其被提到的微博条数。如果这样的话题不唯一,则输出按字母序最小的话题,并在第三行输出And k more …,其中k是另外几条热门话题的条数。输入保证至少存在一条话题。

注意:两条话题被认为是相同的,如果在去掉所有非英文字母和数字的符号、并忽略大小写区别后,它们是相同的字符串;同时它们有完全相同的分词。输出时除首字母大写外,只保留小写英文字母和数字,并用一个空格分隔原文中的单词。

输入样例:

4
This is a #test of topic#.
Another #Test of topic.#
This is a #Hot# #Hot# topic
Another #hot!# #Hot# topic

输出样例:

Hot
2
And 1 more ...

思路

其他字符当作分词标记(空格)。
头尾的空格,以及连续的后面空格都不要
还是map与multimap的使用
注意multimap的增加不能使用[],要使用insert

有空再看吧…

代码

#include<bits/stdc++.h>
using namespace std;
map<string, int> mp;
void topic(string s) {
	int a=0, flag=0;
	set<string> st;
	for(int i=0; s[i]; i++) {
		if(s[i]=='#') {
			if(flag==0) flag = 1, a = i;
			else { //有一个话题
				string tmp = "";
				for(int j=a+1; j<i; j++) {
					if(isalpha(s[j])||isdigit(s[j])) tmp += tolower(s[j]);
					else if(j>0 && j!=i-1 && tmp.back()!=' ') tmp += ' ';
				}
				if(st.find(tmp)==st.end()) {
					st.insert(tmp);
					tmp[0] = toupper(tmp[0]);
					mp[tmp]++;
				}
				flag = 0;
			}
		}
	}
}
int main() {
	int n;
	cin >> n;
	getchar();
	while(n--) {
		string s;
		getline(cin, s);
		topic(s);
	}
	multimap<int, string, greater<int>> res;
	for(auto x:mp) {
		res.insert({x.second, x.first});
//cout << x.first << " " << x.second << endl;
	}
	auto tmp = res.begin();
	cout << tmp->second << endl << tmp->first << endl;
	int cnt = 0;
	for(auto x:res)
		if(x.first==tmp->first) cnt++;
		else break;
	if(cnt>1) printf("And %d more ...", cnt-1);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GCTTTTTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值