#include <iostream>
#include <fstream>
#include <unordered_map>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <queue>
using namespace std;
struct TrieNode {
unordered_map<char, TrieNode*> children;
bool isEndOfWord;
int frequency;
TrieNode() : isEndOfWord(false), frequency(0) {}
};
class Trie {
private:
TrieNode* root;
void getSuggestionsHelper(TrieNode* node, string prefix, vector<pair<string, int>>& results) {
if (node->isEndOfWord)
results.push_back({prefix, node->frequency});
for (auto& pair : node->children) {
getSuggestionsHelper(pair.second, prefix + pair.first, results);
}
}
public:
Trie() { root = new TrieNode(); }
void insert(const string& word) {
TrieNode* current = root;
for (char ch : word) {
ch = tolower(ch);
if (!isalpha(ch)) continue;
if (!current->children[ch]) current->children[ch] = new TrieNode();
current = current->children[ch];
}
current->isEndOfWord = true;
current->frequency++;
}
bool search(const string& word) {
TrieNode* current = root;
for (char ch : word) {
ch = tolower(ch);
if (!isalpha(ch)) continue;
if (!current->children[ch]) return false;
current = current->children[ch];
}
return current->isEndOfWord;
}
vector<pair<string, int>> getSuggestions(const string& prefix) {
TrieNode* current = root;
for (char ch : prefix) {
ch = tolower(ch);
if (!isalpha(ch)) continue;
if (!current->children[ch]) return {};
current = current->children[ch];
}
vector<pair<string, int>> results;
getSuggestionsHelper(current, prefix, results);
sort(results.begin(), results.end(), [](auto& a, auto& b) {
return b.second < a.second;
});
return results;
}
void save(ofstream& out, TrieNode* node, string path = "") {
if (node->isEndOfWord)
out << path << " " << node->frequency << endl;
for (auto& p : node->children) {
save(out, p.second, path + p.first);
}
}
void saveToFile(const string& filename) {
ofstream out(filename);
if (out.is_open()) {
save(out, root);
out.close();
}
}
void loadFromFile(const string& filename) {
ifstream in(filename);
string word;
int freq;
while (in >> word >> freq) {
TrieNode* current = root;
for (char ch : word) {
if (!current->children[ch]) current->children[ch] = new TrieNode();
current = current->children[ch];
}
current->isEndOfWord = true;
current->frequency = freq;
}
in.close();
}
};
// ---------------------------
// Ung dung 1: Kiem tra chinh ta
void spellChecker(Trie& trie) {
ifstream dictFile("words.txt");
if (!dictFile.is_open()) {
cout << "Khong the mo file words.txt\n";
return;
}
string word;
while (dictFile >> word) {
trie.insert(word);
}
dictFile.close();
cout << "Nhap ten file van ban can kiem tra: ";
string textPath;
getline(cin, textPath);
ifstream textFile(textPath);
if (!textFile.is_open()) {
cout << "Khong the mo file van ban!\n";
return;
}
ofstream outFile("misspelled.txt");
string line;
while (getline(textFile, line)) {
stringstream ss(line);
while (ss >> word) {
word.erase(remove_if(word.begin(), word.end(), [](char ch) {
return !isalpha(ch);
}), word.end());
if (!trie.search(word)) {
cout << "Sai chinh ta: " << word << endl;
outFile << word << endl;
}
}
}
textFile.close();
outFile.close();
}
// ---------------------------
// Ung dung 2: Goi y hoan thien tu
void autocomplete(Trie& trie) {
cout << "Nhap ten file chua du lieu nguoi dung: ";
string inputFile;
getline(cin, inputFile);
ifstream in(inputFile);
string word;
while (in >> word) {
trie.insert(word);
}
in.close();
string prefix;
cout << "Nhap tien to can goi y (>= 2 ky tu, go 'exit' de thoat): ";
while (cin >> prefix) {
if (prefix == "exit") break;
if (prefix.size() < 2) {
cout << "Vui long nhap it nhat 2 ky tu.\n";
continue;
}
auto suggestions = trie.getSuggestions(prefix);
if (suggestions.empty()) {
cout << "Khong tim thay goi y.\n";
} else {
cout << "Goi y:\n";
for (auto& [w, freq] : suggestions)
cout << w << " (" << freq << ")\n";
}
cout << "\nNhap tiep hoac go 'exit' de thoat: ";
}
trie.saveToFile("user_trie.txt");
cout << "Da luu lai cay prefix.\n";
}
// ---------------------------
// Chuong trinh chinh
int main() {
Trie trie;
int choice;
cout << "==== CHUONG TRINH CAY PREFIX (TRIE) ====\n";
cout << "1. Kiem tra chinh ta\n";
cout << "2. Goi y hoan thien tu\n";
cout << "3. Thoat\n";
cout << "========================================\n";
cout << "Nhap lua chon: ";
cin >> choice;
cin.ignore();
if (choice == 1) {
spellChecker(trie);
} else if (choice == 2) {
autocomplete(trie);
} else {
cout << "Thoat chuong trinh.\n";
}
return 0;
}