题目:《算法竞赛入门经典》刘汝佳 5-4 反片语 (ananagrams ,UVa 156)P113
输入一些单词,找出满足如下条件的单词:该单词不能通过字母重排,得到文本中的另一个单词。在判断是否满足条件时,字母不分大小写,但在输出是应保留输入中的大小写,按字典序进行排序(所有大写字母在所有小写字母的前面)。
样例输入:
ladder came tape soon leader acme RIDE lone Dreis peat
ScAlE orb eye Rides dealer NotE derail LaCes drIed noel dire Disk mace Rob dries
样例输出:
Disk NotE derail drIed eye ladder soon
分析:
总体思想:将每个单词“标准化”,即全部转化成小写字母,再进行排序,然后放入map中进行统计。
具体步骤:1、读入一个单词的字符串,放入vector<string>words中;将单词的字符串按上述处理后放入map<string,int>cnt中。
2、将words数组中的单词取出,通过转化在map中查找,如果键值为1,说明这个单词为满足题目要求的单词。
3、将满足题目要求的单词放入两一个vector数组中,让其自动按照字典序进行升序排列。最后输出。
代码:
#include<iostream>
#include<string>
#include<cctype>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
map<string,int> cnt;
vector<string> words;
// 将单词s进行“标准化”
string repr(string s) {
string ans = s;
for(int i = 0; i < ans.length(); 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 r = repr(s);
if(!cnt.count(r)) cnt[r] = 0;
cnt[r]++;
}
vector<string> ans;
for(int i = 0; i < words.size(); i++)
if(cnt[repr(words[i])] == 1) ans.push_back(words[i]);
sort(ans.begin(), ans.end());
for(int i = 0; i < ans.size(); i++)
cout << ans[i] << "\n";
return 0;
}
我嫌弃每次调试都需要输入,太麻烦,提前将字符串写好,然后进行处理。
逻辑和上面一样,但最后没有按照字典序输出。(字符串太长,输入换行用‘\’)
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
string trans(string *s)
{
string ans=*s;
int len=ans.length();
int i;
for(i=0;i<len;i++)
ans[i]=tolower(ans[i]);
sort(ans.begin(),ans.end());
return ans;
}
int main()
{
map<string,int>only;
vector<string>words;
//vector<int>flag;//用于标记words中独一无二的单词
string s="ladder came tape soon leader acme RIDE lone Dreis peat \
ScAlE orb eye Rides dealer NotE derail LaCes \
drIed noel dire Disk mace Rob dries";//太长换行输入
cout<<s<<endl<<endl;
stringstream ss;
ss<<s;
string s1;
while(ss>>s1)
{
words.push_back(s1);
only[trans(&s1)]++;
}
int size=words.size();
for(int i=0;i<size;i++)
{
if(only[trans(&words[i])]==1)
cout<<words[i]<<" ";
}
}
运行结果:
参考文章:
funny:1、map可以用来判断是否重复。
2、为什么题目翻译成“反片语”?
anagrams:字谜游戏(由颠倒字母顺序而构成的字[短语]( anagram的名词复数 ))