-
Notifications
You must be signed in to change notification settings - Fork 0
/
StudentSpellCheck.cpp
156 lines (147 loc) · 5.52 KB
/
StudentSpellCheck.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "StudentSpellCheck.h"
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
SpellCheck* createSpellCheck()
{
return new StudentSpellCheck;
}
void StudentSpellCheck::trieDestructorHelper(trieNode* node)
{
if (node == nullptr)
return;
for (int i = 0; i < 27; i++)
trieDestructorHelper(node->children[i]); // Recursively destroying all trie nodes
delete node;
}
StudentSpellCheck::~StudentSpellCheck() {
trieDestructorHelper(root);
}
void StudentSpellCheck::insert(trieNode *root, std::string word) // Inserting into root
{
trieNode *pCrawl = root;
for (int i = 0; i < word.length(); i++)
{
char c = word[i];
word[i] = tolower(c);
if ((97 <= c && c <= 122) || c == '\'')
{
int index = word[i] - 'a' + 1;
if (c == '\'')
index = 0;
if (!pCrawl->children[index]) // Searching to see if a child/letter is not contained
pCrawl->children[index] = getNode(); // If not contained, make a new node with it
pCrawl = pCrawl->children[index]; // Have current node move to the child just created or just looked at
}
}
pCrawl->isEndOfWord = true;
}
bool StudentSpellCheck::search(trieNode *root, std::string word) // Finding word in dictionary, O(L)
{
trieNode *pCrawl = root;
for (int i = 0; i < word.length(); i++)
{
char c = word[i];
word[i] = tolower(c);
int index = word[i] - 'a' + 1;
if (word[i] == '\'')
index = 0;
if (!pCrawl->children[index]) // Searching to see if a child/letter is not contained
return false; // If doesn't contain appropriate child for next letter, return false
pCrawl = pCrawl->children[index]; // Move to the node, if contained
}
return (pCrawl != nullptr && pCrawl->isEndOfWord); // If reach end of word and pCrawl was not a nullpointer, return true
}
bool StudentSpellCheck::load(std::string dictionaryFile) {
std::ifstream infile(dictionaryFile);
if (!infile)
return false;
if (root != nullptr)
trieDestructorHelper(root); // If dictionary already loaded and want to load a new dictionary, must clear out the old dictionary
root = getNode();
std::string s;
while (getline(infile, s))
insert(root, s); // Inserting all words into trie
return true;
}
bool StudentSpellCheck::spellCheck(std::string word, int max_suggestions, std::vector<std::string>& suggestions) {
for (int i = 0; i < word.size(); i++)
{
char c = word[i];
word[i] = tolower(c); // Making word all lower-case, O(L)
}
if (search(root, word)) // O(L) time
return true;
else
{
suggestions.clear();
int count = 0;
for (int i = 0; i < word.size(); i++) // L. For each letter, we will replace the letter with all possible letters and apostrophe and search the dictionary for it. All other letters remain the same
{
std::string replacementLook = word;
for (int j = 0; j < 27; j++) // L * 27
{
std::string charLook = "";
if (j == 0)
charLook += '\'';
else
charLook += j + 96;
replacementLook = replacementLook.replace(i, 1, charLook); // L * 27 * L. Replacing char with new char in alphabet
if (search(root, replacementLook) && count < max_suggestions) //L * 27 * L
{
suggestions.push_back(replacementLook); // Runs up to max_suggestions times, and is O(1), so L*L*27 + max_suggestions*1. Adds words which are one letter different from word to
count++;
}
}
}
return false;
}
}
std::string StudentSpellCheck::lineDivider(std::string line, int &startPos, int &endPos)
{
std::string newWord = "";
int i = startPos;
char c = line.at(i);
bool wasChar = false;
while (i < line.size()) // Loop through all possible non-letters until the first real letter
{
c = line.at(i);
if (isalpha(c) || c == '\'')
break;
i++;
}
startPos = i; // Starting location for word you're checking
while (i < line.size()) // Loop through and add all letters or apostrophes starting at the first letter in the string
{
c = line.at(i);
i++;
if (!(isalpha(c) || c == '\''))
{ wasChar = true;
break;
}
newWord += c; // Adding all letters to word
}
endPos = i - 2; // Ending location for word found
if (i == line.size() && !wasChar)
endPos = i - 1; // Here since when i == line.size(), i won't be incremented so have to properly adjust endPos
return newWord;
}
void StudentSpellCheck::spellCheckLine(const std::string& line, std::vector<SpellCheck::Position>& problems) {
int startPos = 0, endPos = 0;
int lineSize = line.size();
std::string lineParts = line;
while (startPos < lineSize) // Maybe chance back to lineSize - 1
{
std::string checkWord = lineDivider(lineParts, startPos, endPos); // Getting word
if (checkWord == "")
break; // If no words on line, just break
if(!search(root, checkWord)) // Searching for parsed word in dictionary
{
Position wordPosition = {startPos, endPos};
problems.push_back(wordPosition); // If not found in dictionary, add to problems with proper startPos and endPos
}
startPos = endPos + 1;
}
// TODO
}