UVA 156 Ananagrams STL应用

https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=92

给定若干单词,按字典序输出不存在重排的单词。(经测试,不包含重复的单词

重排单词:每个字母出现次数一样,但顺序不同,即对单词序列的一个排序

思路分析

是否满足重排可转换为等价问题:单词的构成字母与顺序无关,有两种解决思路(标准化

  • 字母计数:统计每个字母出现次数,若一致,说明满足重排
map<map<char,int>, int>dict; // 每个单词的字母出现次数->出现次数
  • 统一排序:都按升序排列,若得到相同序列,说明满足重排
map<string, int> dict; // 标准化单词->出现次数

因此在标准化单词(全转为小写)后,边可按照不同思路统计次数,并记录相应到旧单词映射

  • 定义set ans; 存储输出结果,自动按字典序排列

遍历每个标准化单词,若其出现次数为1,插入ans集合中,最后输出即可

AC代码(C++11,map标准化,顺序无关)

统一排序

#include<bits/stdc++.h>
using namespace std;
map<string, int> dict; // 标准化单词->出现次数
map<string, string> trans; // 单词字母出现次数->原单词
set<string> ans; // 存储输出结果,按字典序排列
string s, st;
int main() {
    while (cin >>s && s!= "#") {
        st = s;
        for (auto& ch : st) // 转为小写
            if (ch >= 'A' && ch <= 'Z') ch = tolower(ch); // 转为小写
        sort(st.begin(), st.end()); // 升序排列,顺序无关
        dict[st]++; // 统计次数
        trans[st] = s; // 记录原单词
    }
    for (auto p : dict) if (p.second == 1) ans.insert(trans[p.first]); // 出现次数1表示非重排单词
    for (auto& p : ans) cout <<p <<endl; // 直接输出剩下的单词
    return 0;
}

字母计数

#include<bits/stdc++.h>
using namespace std;
map<map<char,int>, int>dict; // 每个单词的字母出现次数->出现次数
map<map<char,int>, string> trans; // 单词字母出现次数->原单词
set<string> ans; // 存储输出结果,按字典序排列
string s, st;
int main() {
    while (cin >>s && s!= "#") {
        st = s;
        map<char, int> mp;
        for (auto& ch : st) {
            if (ch >= 'A' && ch <= 'Z') ch = tolower(ch); // 转为小写
            mp[ch] ++; // 统计每个字符出现次数
        }
        dict[mp]++; // 统计次数
        trans[mp] = s; // 记录原单词
    }
    for (auto p : dict) if (p.second == 1) ans.insert(trans[p.first]); // 出现次数1表示非重排单词
    for (auto& p : ans) cout <<p <<endl; // 直接输出剩下的单词
    return 0;
}
上一篇:UVA 11988(list, deque)


下一篇:算法竞赛入门经典(第二版)3-11换低挡装置UVA-1588