Uva156:反片语Ananagrams(详解包看懂)

文章讲述了如何使用C++编程解决一个算法问题:给定一组单词,找出那些不能通过重新排列字母形成其他单词的字符串。解决方案包括将单词转为小写并排序,利用map存储排序后的单词及其出现次数,最后输出仅出现一次的单词。

一、题目

输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文本中的另外一个单词。在判断是否满足条件时,字母不分大小写,但在输出时应保留输入中的大小写,按字典序进行排列(所有大写字母在所有小写字母的前面)。

样例输入:
ladder came tape soon leader acme RIDE lone Dreis peatScAlE orb eye Rides dealer NotE derail LaCeS drIednoel dire Disk mace Rob dries

样例输出:
Disk
NotE
derail
drIed
eye
ladder
soon

二、 思路分析,步骤和代码以及说明

1.思路分析

题目意思就是找一些单词,这些单词可以进行字母重排,比如come可以重排为omec,如果重排之后和文本中任意一个单词都不一样,就输出。

这题呢还是比较训练思维的,要先把所有字母变成小写的,然后把每个单词都排序,比如come按照大小顺序排出来后是cemo,再把它们放到map中统计。如果两个单词一模一样,就不用输出了。

2.步骤

一个一个输入单词并用vector把单词装进去→用tolower函数把所有大写字母变成小写的并排好序→用map映射看元素出现次数,没有出现过的话就添加进新的vector数组ans中→输出ans内容。
注意 两个数组,一个用来存原本的单词信息,一个用来存符合要求的单词信息。一个映射,用来判断单词是否出现过,如果第一次出现就让其出现次数从0变为1。
这样做可能开辟的内存空间比较多,但是他很快速并且容易理解。反正我写了很多段代码,这有这一段最好

3.代码

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<cctype>
#include<algorithm>
using namespace std;

map<string, int>cnt;
vector<string> words;

//把所有大写字母变成小写字母并排序
string transfer(const string& s) {
	string ans = s;	
	for (int i = 0; i < ans.length(); i++) {
		if (ans[i] >= 'A' && 'Z' >= ans[i])
			ans[i] = tolower(ans[i]);
	}
	sort(ans.begin(), ans.end());
	return ans;
}

int main() {
	int n = 0;
	string s;
	while (cin >> s) {
		if (s[0] == '#') break;
		words.push_back(s);
		string t;
		t = transfer(s);
		if (!cnt.count(t))cnt[t] = 0;//如果元素没有出现过就赋值0
		cnt[t]++;//标记该元素已经出现过了
	}
	vector<string> ans;
	for (int i = 0; i < words.size(); i++)
		if (cnt[transfer(words[i])] == 1) ans.push_back(words[i]);//如果只出现过一次就添加进vector
	sort(ans.begin(), ans.end());
	for (int i = 0; i < ans.size(); i++)
		cout << ans[i] << "\n";
	return 0;
}

4.说明

map底层是红黑树实现的,具有自动排序的功能,有一对对的hash值,左边的叫关键字(key),右边的叫关键字的值(value)。
在这里插入图片描述
一一映射的关系中,一个名字对应一个电话号码,只要搜索名字,就能得到相应的电话号码,搜索电话号码也能得到相应的名字。map.count()是返回元素出现的次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值