从字符串中删除重复字符
Posted
技术标签:
【中文标题】从字符串中删除重复字符【英文标题】:Remove repeating characters from string 【发布时间】:2014-09-20 08:57:27 【问题描述】:我有一个字符串,例如acaddef
或 bbaaddgg
。我必须尽快从其中删除所有重复的字符。因此,例如,pooaatat
之后应该看起来像 poat
和 ggaatpop
应该看起来像 gatpo
。是否有任何内置函数或算法可以快速做到这一点?我试图搜索 STL,但没有满意的结果。
【问题讨论】:
对字符串进行切片需要了解字符集和编码(以及您希望应用于算法的任何简化假设/输入验证)。您使用的是 Unicode/UTF-8 吗? (对于控制台程序,在 Linus 上运行:locale
,在 Windows 上:chcp
。)
【参考方案1】:
好的,这里有 4 种不同的解决方案。
固定数组
std::string str = "pooaatat";
// Prints "poat"
short count[256] = 0;
std::copy_if(str.begin(), str.end(), std::ostream_iterator<char>(std::cout),
[&](unsigned char c) return count[c]++ == 0; );
计数算法+迭代器
std::string str = "pooaatat";
// Prints "poat"
std::string::iterator iter = str.begin();
std::copy_if(str.begin(), str.end(), std::ostream_iterator<char>(std::cout),
[&](char c) return !std::count(str.begin(), iter++, c); );
无序集
std::string str = "pooaatat";
// Prints "poat"
std::unordered_set<char> container;
std::copy_if(str.begin(), str.end(), std::ostream_iterator<char>(std::cout),
[&](char c) return container.insert(c).second; );
无序映射
std::string str = "pooaatat";
// Prints "poat"
std::unordered_map<char, int> container;
std::copy_if(str.begin(), str.end(), std::ostream_iterator<char>(std::cout),
[&](char c) return container[c]++ == 0; );
【讨论】:
它应该打印“poat”,因为双“t”也应该被删除【参考方案2】:AFAIK,没有内置算法可以做到这一点。如果您只想删除连续的重复字符,std::unique
算法是有效的。
但是您可以遵循以下简单的方法:
如果字符串只包含 ASCII 字符,你可以形成一个布尔数组 A[256] 表示是否已经遇到了相应的字符。
然后简单地遍历输入字符串,如果 A[character] 仍然为 0,则将字符复制到输出(并使 A[character] = 1)。
如果字符串中包含任意字符,则可以使用std::unordered_map
或std::map
的char 转换为int。
【讨论】:
ASCII 仅包含 128 个代码点,并且在很大程度上无关紧要。对于您的 256 元素数组,限制只是字符集最多有 256 个代码点,每个代码点都有一个 1 字节的编码,并且没有“组合字符”,这需要与前面的代码点保持一致。跨度> 【参考方案3】:内置的正则表达式应该是高效的,即
#include <regex>
[...]
const std::regex pattern("([\\w ])(?!\\1)");
string s = "ssha3akjssss42jj 234444 203488842882387 heeelloooo";
std::string result;
for (std::sregex_iterator i(s.begin(), s.end(), pattern), end; i != end; ++i)
result.append((*i)[1]);
std::cout << result << std::endl;
当然,您可以根据需要修改 cpaturing 组。 好消息是它已经在 Visual Studio 2010 tr1 中得到支持。然而,gcc 4.8 似乎有一个带有正则表达式迭代器的problem。
【讨论】:
以上是关于从字符串中删除重复字符的主要内容,如果未能解决你的问题,请参考以下文章