I a building a program that takes phone numbers as input. It should then check if there already exists a phone number which is a prefix in our new number. Example:
Input:
555 //This is okay
5556888 //This is not okay because 555 is a registered number
556888 //this is okay
5568889 // Not okay
Hope you understand what I'm getting at.
I have implemented two functions:
Contains That should check if the number or prefixes already exist.
bool PrefixStringSet::contains(string s)
{
NodePtr temp = root;
for ( int i = 0; i < s.size(); i++)
{
if(temp->children[s[i] - '0'] == NULL)
{
return false;
}
temp = temp->children[s[i] - '0'];
}
return true;
}
Insert
bool PrefixStringSet::insert(string s)
{
if(contains(s) == true)
{
return false;
}
NodePtr temp = root;
for (int i = 0; i < s.size(); i++)
{
int number = (int)s[i] - (int)'0';
if(temp->children[number] == NULL)
{
temp->children[number] = new TrieNode;
temp = temp->children[number];
}
}
return true;
}
As it stands now contains only check's if the number has already been registered. I can't figure out a good way to check if the prefix is already a number. Should I implement it in contains or maybe in the insert function(Maybe have a loop go trough each prefix, starting with the first number?)
Any help appreciated.
Main
int main()
{
PrefixStringSet Phonenumber;
int HowManyPhoneNumbers;
cin >> HowManyPhoneNumbers;
for(int i = 0 ; i<HowManyPhoneNumbers ; i++)
{
string temp;
cin >> temp;
if(Phonenumber.insert(temp) == true)
{
cout << "Yes" << endl;
}
else
{
cout << "NO" <<endl;
}
}
return 0;
}
Edit Insert:
bool PrefixStringSet::insert(string s)
{
if(contains(s) == true)
{
return false;
}
NodePtr temp = root;
for (int i = 0; i < s.size(); i++)
{
int number = (int)s[i] - (int)'0';
if(temp->children[number] == NULL)
{
temp->children[number] = new TrieNode;
}
temp = temp->children[number];
}
return true;
}
Contains:
bool PrefixStringSet::contains(string s)
{
NodePtr temp = root;
for ( int i = 0; i < s.size(); i++)
{
if(temp->is_leaf())
{
return false;
}
if(temp->children[s[i] - '0'] == NULL)
{
return false;
}
temp = temp->children[s[i] - '0'];
}
return true;
}
input:
911
YES
9111 /Not working
Yes
91 //Working
NO
edit2:
bool PrefixStringSet::contains(string s)
{
NodePtr temp = root;
for ( int i = 0; i < s.size(); i++)
{
if(temp->is_leaf())
{
return false;
}
if (temp !=root && temp->is_leaf())
{
return true;
}
if(temp->children[s[i] - '0'] == NULL)
{
return false;
}
temp = temp->children[s[i] - '0'];
}
return true;
}
In PrefixStringSet::contains(string s)
if(temp->children[s[i] - '0'] == NULL)
{
return false;
}
Instead of returning false
directly, you should check whether temp
has any non-NULL child.
That is,
if(temp->children[s[i] - '0'] == NULL)
{
return (temp != root && temp->is_leaf());
}
Because if temp
has no child at all, then the string s
's prefix already exists.
Edit: Check temp != root
to avoid being stuck at empty trie.
The most efficient implementation of TrieNode::hasAnyChild()
depends on how TrieNode::children
was stored, which you didn't show in the question statement. If your trie only accepts decimal digits, then simply go through all children should be good enough.
By the way, in PrefixStringSet::insert(string s)
int number = (int)s[i] - (int)'0';
if(temp->children[number] == NULL)
{
temp->children[number] = new TrieNode;
temp = temp->children[number];
}
The line temp = temp->children[number];
should be moved after the end of if
block since you need to move temp
one step further no matter you created a new node or not.