Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Java
*.class
*.log
*.jar
*.war
*.ear
# Build directories
target/
build/
out/
bin/
# Editor temporary files
*.swp
*~
# IDE files
.idea/
.vscode/
*.iml
*.iws
*.ipr
# Other
.DS_Store
Thumbs.db
64 changes: 64 additions & 0 deletions Search suggestion system/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Java Search Suggestions System (Trie)

This is a simple and efficient command-line implementation of a search suggestions system (autocomplete) in Java. It uses a **Trie (Prefix Tree)** data structure to store a dictionary of words and find all words that match a given prefix.

This project is a clean, single-file implementation suitable for demonstrating the practical application of a Trie.

## Features

* **Trie-Based:** Uses a `TrieNode` class with a `HashMap` for efficient, case-insensitive prefix lookups.
* **Case-Insensitive:** All inserted words and prefixes are handled in lowercase.
* **Interactive:** Includes a `main` method that allows you to load a dictionary and test prefixes in real-time.
* **Loads from File:** Reads its dictionary from an external `dictionary.txt` file.

## How to Compile and Run

This project consists of a single Java file and a dictionary text file.

**1. Compile the Code:**
Open your terminal in the project directory and run:

```bash
javac SearchSuggestions.java
```

**2. Run the Program:**
After compiling, run the program:

```bash
java SearchSuggestions
```

**3. Example Session:**
The program will first load the words from `dictionary.txt`.

```text
Loading dictionary from 'dictionary.txt'...
Successfully loaded 10 words.

Enter prefix to search (or 'q' to quit): pro
Suggestions for 'pro':
-> profile
-> program
-> project
-> python

Enter prefix to search (or 'q' to quit): app
Suggestions for 'app':
-> app
-> apple
-> apply
-> application

Enter prefix to search (or 'q' to quit): q
Goodbye!
```

## How It Works

* `TrieNode`: A private inner class holds a `Map<Character, TrieNode>` for its children and a `boolean` to mark the end of a word.
* `insert(String word)`: Iterates through each character of the word, creating new nodes in the Trie as needed.
* `getSuggestions(String prefix)`:
1. Traverses the Trie to the node corresponding to the last character of the prefix.
2. If the prefix path doesn't exist, it returns an empty list.
3. If it does, it calls a recursive helper `findAllWords()` to explore all child paths from that node and collect all complete words.
130 changes: 130 additions & 0 deletions Search suggestion system/SearchSuggestions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class SearchSuggestions {

private class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
boolean isEndOfWord;
}

private final TrieNode root;

public SearchSuggestions() {
root = new TrieNode();
}

public void insert(String word) {
if (word == null || word.isEmpty()) {
return;
}
TrieNode node = root;
for (char c : word.toLowerCase().toCharArray()) {
node = node.children.computeIfAbsent(c, k -> new TrieNode());
}
node.isEndOfWord = true;
}

public List<String> getSuggestions(String prefix) {
if (prefix == null) {
return Collections.emptyList();
}
String lowerPrefix = prefix.toLowerCase();
TrieNode node = root;

for (char c : lowerPrefix.toCharArray()) {
node = node.children.get(c);
if (node == null) {
return Collections.emptyList();
}
}

List<String> suggestions = new ArrayList<>();
findAllWords(node, new StringBuilder(lowerPrefix), suggestions);
return suggestions;
}

private void findAllWords(TrieNode node, StringBuilder currentWord, List<String> suggestions) {
if (node.isEndOfWord) {
suggestions.add(currentWord.toString());
}

for (Map.Entry<Character, TrieNode> entry : node.children.entrySet()) {
currentWord.append(entry.getKey());
findAllWords(entry.getValue(), currentWord, suggestions);
currentWord.setLength(currentWord.length() - 1); // Backtrack
}
}

/**
* Loads words from a specified dictionary file into the Trie.
*/
private static int loadDictionary(SearchSuggestions trie, String filename) {
int wordCount = 0;
// The dictionary file is inside the same folder, so the path is simple.
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
if (!line.trim().isEmpty()) {
trie.insert(line.trim());
wordCount++;
}
}
} catch (FileNotFoundException e) {
System.err.println("Error: Dictionary file not found: " + filename);
} catch (IOException e) {
System.err.println("Error: Failed to read dictionary file: " + e.getMessage());
}
return wordCount;
}

public static void main(String[] args) {
SearchSuggestions trie = new SearchSuggestions();

// Looks for the file in the same directory as the .java file.
// When running, you must be "inside" this folder.
String dictionaryFile = "dictionary.txt";
System.out.println("Loading dictionary from '" + dictionaryFile + "'...");

int wordCount = loadDictionary(trie, dictionaryFile);

if (wordCount == 0) {
System.err.println("Dictionary is empty or could not be loaded. Exiting.");
return;
}

System.out.println("Successfully loaded " + wordCount + " words.");

try (Scanner scanner = new Scanner(System.in)) {

while (true) {
System.out.print("\nEnter prefix to search (or 'q' to quit): ");
String prefix = scanner.nextLine();

if (prefix.equalsIgnoreCase("q") || prefix.isEmpty()) {
break;
}

List<String> suggestions = trie.getSuggestions(prefix);

if (suggestions.isEmpty()) {
System.out.println("No suggestions found for '" + prefix + "'.");
} else {
System.out.println("Suggestions for '" + prefix + "':");
for (String suggestion : suggestions) {
System.out.println(" -> " + suggestion);
}
}
}
}
System.out.println("Goodbye!");
}
}
22 changes: 22 additions & 0 deletions Search suggestion system/dictionary.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apple
app
application
apply
apricot
banana
band
bank
bat
project
program
profile
java
javascript
react
node
sql
system
search
suggestion
trie
tree
Loading