给定电话目录中存在的联系人列表。任务是对电话目录实施搜索查询。字符串“ str ”上的搜索查询显示所有前缀为“ str ”的联系人。搜索函数的一个特殊属性是,当用户从联系人列表中搜索联系人时,在用户输入每个字符后会显示建议(带有前缀的联系人作为输入的字符串)。
注意:列表中的联系人仅包含小写字母。
例子:
Input : contacts [] = {“gforgeeks” , “geeksquiz” }
Query String = “gekk”
Output : Suggestions based on "g" are
geeksquiz
gforgeeks
Suggestions based on "ge" are
geeksquiz
No Results Found for "gek"
No Results Found for "gekk"
使用Trie数据结构可以有效地实现电话目录。我们将所有联系人插入到Trie中。
通常,在Trie上的搜索查询是确定该字符串是否存在于Trie中,但是在这种情况下,要求我们查找所有前缀为’str’的所有字符串。这等效于在图形上进行DFS遍历。在Trie节点上,访问相邻的Trie节点,然后递归执行此操作,直到不再有相邻节点为止。这种递归函数需要2个参数作为一个字典树节点指向当前的字典树节点被访问和其他作为存储字符串迄今为止发现的前缀为“STR”的字符串。
每个Trie节点都存储一个布尔变量’isLast’,如果该节点表示contact(word)的末尾,则为true。
// This function displays all words with given
// prefix. "node" represents last node when
// path from root follows characters of "prefix".
displayContacts (TreiNode node, string prefix)
If (node.isLast is true)
display prefix
// finding adjacent nodes
for each character ‘i’ in lower case Alphabets
if (node.child[i] != NULL)
displayContacts(node.child[i], prefix+i)
用户将进入由字符字符串的字符,我们需要每一个输入的字符后形成的词头显示建议。
因此,找到以形成的字符串开头的前缀的一种方法是检查Trie中是否存在该前缀,如果存在,则调用displayContacts()函数。通过这种方法,在每个输入的字符,我们检查字符串存在于Trie中。
无需一次又一次地检查,我们可以维护一个指针prevNode ‘,该指针指向用户最后输入的字符所对应的TrieNode,现在,当用户输入另一个字符进行检查时,我们需要检查子节点中的’prevNode’如果在Trie中存在。如果新前缀不在Trie中,那么在Trie中也找不到在’prefix’之后输入字符形成的所有字符串。因此,我们打破了用于一一生成前缀的循环,并为所有剩余字符打印“未找到结果”。
C++
// C++ Program to Implement a Phone
// Directory Using Trie Data Structure
#include
using namespace std;
struct TrieNode
{
// Each Trie Node contains a Map 'child'
// where each alphabet points to a Trie
// Node.
// We can also use a fixed size array of
// size 256.
unordered_map child;
// 'isLast' is true if the node represents
// end of a contact
bool isLast;
// Default Constructor
TrieNode()
{
// Initialize all the Trie nodes with NULL
for (char i = 'a'; i <= 'z'; i++)
child[i] = NULL;
isLast = false;
}
};
// Making root NULL for ease so that it doesn't
// have to be passed to all functions.
TrieNode *root = NULL;
// Insert a Contact into the Trie
void insert(string s)
{
int len = s.length();
// 'itr' is used to iterate the Trie Nodes
TrieNode *itr = root;
for (int i = 0; i < len; i++)
{
// Check if the s[i] is already present in
// Trie
TrieNode *nextNode = itr->child[s[i]];
if (nextNode == NULL)
{
// If not found then create a new TrieNode
nextNode = new TrieNode();
// Insert into the Map
itr->child[s[i]] = nextNode;
}
// Move the iterator('itr') ,to point to next
// Trie Node
itr = nextNode;
// If its the last character of the string 's'
// then mark 'isLast' as true
if (i == len - 1)
itr->isLast = true;
}
}
// This function simply displays all dictionary words
// going through current node. String 'prefix'
// represents string corresponding to the path from
// root to curNode.
void displayContactsUtil(TrieNode *curNode, string prefix)
{
// Check if the string 'prefix' ends at this Node
// If yes then display the string found so far
if (curNode->isLast)
cout << prefix << endl;
// Find all the adjacent Nodes to the current
// Node and then call the function recursively
// This is similar to performing DFS on a graph
for (char i = 'a'; i <= 'z'; i++)
{
TrieNode *nextNode = curNode->child[i];
if (nextNode != NULL)
displayContactsUtil(nextNode, prefix + (char)i);
}
}
// Display suggestions after every character enter by
// the user for a given query string 'str'
void displayContacts(string str)
{
TrieNode *prevNode = root;
string prefix = "";
int len = str.length();
// Display the contact List for string formed
// after entering every character
int i;
for (i=0; ichild[lastChar];
// If nothing found, then break the loop as
// no more prefixes are going to be present.
if (curNode == NULL)
{
cout << "nNo Results Found for "" << prefix
<< "" n";
i++;
break;
}
// If present in trie then display all
// the contacts with given prefix.
cout << "nSuggestions based on "" << prefix
<< "" are n";
displayContactsUtil(curNode, prefix);
// Change prevNode for next prefix
prevNode = curNode;
}
// Once search fails for a prefix, we print
// "Not Results Found" for all remaining
// characters of current query string "str".
for (; i
Java
// Java Program to Implement a Phone
// Directory Using Trie Data Structure
import java.util.*;
class TrieNode
{
// Each Trie Node contains a Map 'child'
// where each alphabet points to a Trie
// Node.
HashMap child;
// 'isLast' is true if the node represents
// end of a contact
boolean isLast;
// Default Constructor
public TrieNode()
{
child = new HashMap();
// Initialize all the Trie nodes with NULL
for (char i = 'a'; i <= 'z'; i++)
child.put(i,null);
isLast = false;
}
}
class Trie
{
TrieNode root;
// Insert all the Contacts into the Trie
public void insertIntoTrie(String contacts[])
{
root = new TrieNode();
int n = contacts.length;
for (int i = 0; i < n; i++)
{
insert(contacts[i]);
}
}
// Insert a Contact into the Trie
public void insert(String s)
{
int len = s.length();
// 'itr' is used to iterate the Trie Nodes
TrieNode itr = root;
for (int i = 0; i < len; i++)
{
// Check if the s[i] is already present in
// Trie
TrieNode nextNode = itr.child.get(s.charAt(i));
if (nextNode == null)
{
// If not found then create a new TrieNode
nextNode = new TrieNode();
// Insert into the HashMap
itr.child.put(s.charAt(i),nextNode);
}
// Move the iterator('itr') ,to point to next
// Trie Node
itr = nextNode;
// If its the last character of the string 's'
// then mark 'isLast' as true
if (i == len - 1)
itr.isLast = true;
}
}
// This function simply displays all dictionary words
// going through current node. String 'prefix'
// represents string corresponding to the path from
// root to curNode.
public void displayContactsUtil(TrieNode curNode,
String prefix)
{
// Check if the string 'prefix' ends at this Node
// If yes then display the string found so far
if (curNode.isLast)
System.out.println(prefix);
// Find all the adjacent Nodes to the current
// Node and then call the function recursively
// This is similar to performing DFS on a graph
for (char i = 'a'; i <= 'z'; i++)
{
TrieNode nextNode = curNode.child.get(i);
if (nextNode != null)
{
displayContactsUtil(nextNode, prefix + i);
}
}
}
// Display suggestions after every character enter by
// the user for a given string 'str'
void displayContacts(String str)
{
TrieNode prevNode = root;
// 'flag' denotes whether the string entered
// so far is present in the Contact List
String prefix = "";
int len = str.length();
// Display the contact List for string formed
// after entering every character
int i;
for (i = 0; i < len; i++)
{
// 'str' stores the string entered so far
prefix += str.charAt(i);
// Get the last character entered
char lastChar = prefix.charAt(i);
// Find the Node corresponding to the last
// character of 'str' which is pointed by
// prevNode of the Trie
TrieNode curNode = prevNode.child.get(lastChar);
// If nothing found, then break the loop as
// no more prefixes are going to be present.
if (curNode == null)
{
System.out.println("nNo Results Found for ""
+ prefix + """);
i++;
break;
}
// If present in trie then display all
// the contacts with given prefix.
System.out.println("nSuggestions based on ""
+ prefix + "" are");
displayContactsUtil(curNode, prefix);
// Change prevNode for next prefix
prevNode = curNode;
}
for ( ; i < len; i++)
{
prefix += str.charAt(i);
System.out.println("nNo Results Found for ""
+ prefix + """);
}
}
}
// Driver code
class Main
{
public static void main(String args[])
{
Trie trie = new Trie();
String contacts [] = {"gforgeeks", "geeksquiz"};
trie.insertIntoTrie(contacts);
String query = "gekk";
// Note that the user will enter 'g' then 'e' so
// first display all the strings with prefix as 'g'
// and then all the strings with prefix as 'ge'
trie.displayContacts(query);
}
}
C#
// C# Program to Implement a Phone
// Directory Using Trie Data Structure
using System;
using System.Collections.Generic;
class TrieNode
{
// Each Trie Node contains a Map 'child'
// where each alphabet points to a Trie
// Node.
public Dictionary child;
// 'isLast' is true if the node represents
// end of a contact
public bool isLast;
// Default Constructor
public TrieNode()
{
child = new Dictionary();
// Initialize all the Trie nodes with NULL
for (char i = 'a'; i <= 'z'; i++)
child.Add(i, null);
isLast = false;
}
}
class Trie
{
public TrieNode root;
// Insert all the Contacts into the Trie
public void insertIntoTrie(String []contacts)
{
root = new TrieNode();
int n = contacts.Length;
for (int i = 0; i < n; i++)
{
insert(contacts[i]);
}
}
// Insert a Contact into the Trie
public void insert(String s)
{
int len = s.Length;
// 'itr' is used to iterate the Trie Nodes
TrieNode itr = root;
for (int i = 0; i < len; i++)
{
// Check if the s[i] is already present in
// Trie
TrieNode nextNode = itr.child[s[i]];
if (nextNode == null)
{
// If not found then create a new TrieNode
nextNode = new TrieNode();
// Insert into the Dictionary
if(itr.child.ContainsKey(s[i]))
itr.child[s[i]] = nextNode;
else
itr.child.Add(s[i], nextNode);
}
// Move the iterator('itr') ,to point to next
// Trie Node
itr = nextNode;
// If its the last character of the string 's'
// then mark 'isLast' as true
if (i == len - 1)
itr.isLast = true;
}
}
// This function simply displays all dictionary words
// going through current node. String 'prefix'
// represents string corresponding to the path from
// root to curNode.
public void displayContactsUtil(TrieNode curNode,
String prefix)
{
// Check if the string 'prefix' ends at this Node
// If yes then display the string found so far
if (curNode.isLast)
Console.WriteLine(prefix);
// Find all the adjacent Nodes to the current
// Node and then call the function recursively
// This is similar to performing DFS on a graph
for (char i = 'a'; i <= 'z'; i++)
{
TrieNode nextNode = curNode.child[i];
if (nextNode != null)
{
displayContactsUtil(nextNode, prefix + i);
}
}
}
// Display suggestions after every character enter by
// the user for a given string 'str'
public void displayContacts(String str)
{
TrieNode prevNode = root;
// 'flag' denotes whether the string entered
// so far is present in the Contact List
String prefix = "";
int len = str.Length;
// Display the contact List for string formed
// after entering every character
int i;
for (i = 0; i < len; i++)
{
// 'str' stores the string entered so far
prefix += str[i];
// Get the last character entered
char lastChar = prefix[i];
// Find the Node corresponding to the last
// character of 'str' which is pointed by
// prevNode of the Trie
TrieNode curNode = prevNode.child[lastChar];
// If nothing found, then break the loop as
// no more prefixes are going to be present.
if (curNode == null)
{
Console.WriteLine("\nNo Results Found for'"
+ prefix + "'");
i++;
break;
}
// If present in trie then display all
// the contacts with given prefix.
Console.WriteLine("Suggestions based on '"
+ prefix + "' are");
displayContactsUtil(curNode, prefix);
// Change prevNode for next prefix
prevNode = curNode;
}
for ( ; i < len; i++)
{
prefix += str[i];
Console.WriteLine("\nNo Results Found for '"
+ prefix + "'");
}
}
}
// Driver code
public class GFG
{
public static void Main(String []args)
{
Trie trie = new Trie();
String []contacts = {"gforgeeks", "geeksquiz"};
trie.insertIntoTrie(contacts);
String query = "gekk";
// Note that the user will enter 'g' then 'e' so
// first display all the strings with prefix as 'g'
// and then all the strings with prefix as 'ge'
trie.displayContacts(query);
}
}
// This code is contributed by PrinciRaj1992
输出:
Suggestions based on "g" are
geeksquiz
gforgeeks
Suggestions based on "ge" are
geeksquiz
No Results Found for "gek"
No Results Found for "gekk"