Я всегда верил, что если вы копируете и вставляете код, то есть более элегантное решение. В настоящее время я реализую строковый суффикс trie в C ++ и имею две практически идентичные функции, которые отличаются только оператором return.
Первая функция проверяет наличие подстроки, вторая — суффикс (все строки имеют символ #
добавлено в конец).
подстрока (строка S)
bool Trie::substring(string S){
Node* currentNode = &nodes[0]; //root
for(unsigned int i = 0; i < S.length(); i++){
int edgeIndex = currentNode->childLoc(S.at(i));
if(edgeIndex == -1)
return false;
else currentNode = currentNode->getEdge(edgeIndex)->getTo();
}
return true;
}
суффикс (строка S)
bool Trie::suffix(string S){
Node* currentNode = &nodes[0]; //root
for(unsigned int i = 0; i < S.length(); i++){
int edgeIndex = currentNode->childLoc(S.at(i));
if(edgeIndex == -1)
return false;
else currentNode = currentNode->getEdge(edgeIndex)->getTo();
}
return (currentNode->childLoc('#') == -1)? false : true; //this will be the index of the terminating character (if it exists), or -1.
}
Как логически обобщить логику? Возможно, используя шаблоны?
Что я лично делаю в таких обстоятельствах, так это перенесу общий код в функцию, которую я вызываю из нескольких мест, где мне нужно, с указанием общей функциональности. Учти это:
Node* Trie::getCurrentNode (string S){
Node* currentNode = &nodes[0];
for(unsigned int i = 0; i < S.length(); i++){
int edgeIndex = currentNode->childLoc(S.at(i));
if(edgeIndex == -1)
return nullptr;
else currentNode = currentNode->getEdge(edgeIndex)->getTo();
}
return currentNode;
}
А затем используйте его во всех случаях, когда это необходимо:
bool Trie::substring(string S){
return getCurrentNode (S) != nullptr;
}
bool Trie::suffix(string S){
Node* currentNode = getCurrentNode(S);
return currentNode != nullptr && currentNode->childLoc('#') != -1;
// I decided to simplify the return statement in a way François Andrieux suggested, in the comments. It makes your code more readable.
}
Других решений пока нет …