有这样的地图:
typedef std::string Path; // has this format "/<a>/<b>/<c>"
typedef std::vector<std::string> Paths;
typedef std::map<std::string, Paths> PathMapping;
PathMapping mathMapping; // ( "/a/b/c" --> "/a/b/c1", "a/b/c2" )
( "/a/b/d" --> "/a/b/d1", "a/b/d2" )
("/a/b/c/d" --> "a/b/c/d1", "a/b/c/d2" ) // not allowed
如何检查地图中是否存在另一个键的子串?
答案 0 :(得分:2)
map
中的键按字典顺序排序,因此如果一个键A
将成为另一个键B
的前缀,则:
A
出现在B
A
也是A
和B
因此,我们可以在地图中执行简单扫描(m
此处):
auto current = m.begin();
for (auto it = next(current), end = m.end(); it != end; ++it ) {
// Note: if current is not a prefix of "it", then it cannot be a prefix
// of any key that comes after "it", however of course "it" could
// be such a prefix.
// current is not a prefix of "it" if "it" is shorter
if (it->first.size() <= current->first.size()) { current = it; continue; }
// current is not a prefix of "it"
if (it->first.substr(0, current->first.size()) != current->first) {
current = it; continue;
}
// current is a prefix
std::cout << "'" << current->first << "' is a prefix of '" << it->first << "'\n";
}
注意:计算子字符串不是必需的,没有分配的starts_with
函数会好得多,但它确实可以解决这个问题。
您可以查看full code here。
答案 1 :(得分:1)
不改变数据结构:
for (const auto& p : mathMapping)
for (const auto& s : mathMapping)
if (starts_with(p.first, s.first))
// collision
C ++ 03版本将是:
for (PathMapping::const_iterator p = mathMapping.begin(); p != mathMapping.end(); ++p)
for (PathMapping::const_iterator s = mathMapping.begin(); s != mathMapping.end(); ++s)
if (starts_with(p->first, s->first))
// collision
其中starts_with
是提议的here函数之一。
但是如果你可以改变数据结构,我会将每个段分开/
并使用树状容器。