好的我必须使用“* all”之类的输入搜索Trie树,其中*可以是任何字符。我知道使用regex_match匹配搜索字符串,就像其他树一样,在那里搜索整个单词。但由于Trie的搜索算法是按字符进行的,因此我无法将常规搜索算法转换为我的需求。
以下是没有*
的trie搜索的未触及的常规代码 bool Trie::searchWord(string s){
Node* cur = root;
while(cur != NULL){
for(int i = 0; i < s.length(); i++){
Node* tmp = cur->findChild(s[i]);
if(tmp == NULL){
return false;
}//end if
cur = tmp;
}//end for
if(cur->wordMarker()){
return true;
}else{
return false;
}//end if-else
}//end while
return false;
}//end searchWord(s)
Node* Node::findChild(char c){
for(int i = 0; i<mChildren.size(); i++){
Node* tmp = mChildren.at(i);
if(tmp->content() == c){
return tmp;
}//end if
}//end for
return NULL;
}//end findChild(c)
这是我尝试修改它。它适用于常规单词,但不适用于*
bool Trie::searchWordRegex(string s){
Node* cur = root;
while(cur != NULL){
regex reg ;
for(int i = 0; i < s.length(); i++){
if(s[i] == '*'){
reg = regex("(\\w)");
}//end if
Node* tmp = cur->findChildRegex(s[i], reg);
if(tmp == NULL){
return false;
}//end if
cur = tmp;
}//end for
if(cur->wordMarker()){
return true;
}else{
return false;
}//end if-else
}//end while
return false;
}//end searchWord(s)
Node* Node::findChildRegex(char c, regex r){
for(int i = 0; i<mChildren.size(); i++){
Node* tmp = mChildren.at(i);
string s(1,tmp->content());
if(tmp->content() == c || regex_match(s, r)){
return tmp;
}//end if
}//end for
return NULL;
}//end findChild(c)
有没有办法可以修复这些功能?或者像其他树的regex_match一样容易吗?
谢谢。
答案 0 :(得分:0)
由于您将'*'称为字符通配符,因此意图有点令人困惑,但您引用的是正则表达式匹配(实际的正则表达式字符通配符为'。')。我将尝试回答这个问题,假设意图是支持对trie进行完整的正则表达式搜索,或者在trie中搜索通配符。
在Trie中正则表达式匹配
trie通常用于支持快速O(m)操作。它不是处理正则表达式的通常有效的结构。
regular expression matching(DFA / NFA和回溯)有几种算法,并且为了在trie搜索中支持它们,你实际上必须实现一个经过修改的算法来支持子搜索迭代和回溯在trie中用于收集状态/匹配的正则表达式可以匹配。这将具有最低的渐近复杂度,可能是最有效的。
...然而
t几乎具有相同的渐近复杂度来迭代特里结构中的所有字符串,并使用std::regex
和std::regex_match
对正则表达式匹配进行测试。此外,它还使您无需实现相对复杂的正则表达式引擎。
Trie中的通配符匹配
但是,修改代码以支持通配符搜索非常简单。不是使用显式字符搜索每个级别,而是针对通配符('*'或'。')检查搜索字符s[i]
,如果匹配,则可以进入任何子尝试,并且增量i
。虽然,有一点需要注意,你需要能够转义你选择的任何字符作为通配符,因此它仍然是存储在trie中的字符串中的有效字符。