PROGRAMMERS 프로그래머스 : 가사 검색
Updated:
시작하면서
이번 문제는 트라이(Trie) 문제이다.
문제 아이디어
이 문제는 반복된 문자열을 검색해서 찾아야하는 문제이다. 인풋인 queries의 길이가 최대 100,000, words의 길이도 최대 100,000, 단어들의 길이도 최대 10,000이므로 효율적인 검색이 필요하다.
다른 설명 필요 없이 Trie를 사용하면 된다. 여기서 주의할 점은 검색할 때 단어의 길이도 신경을 써주어야 한다.
해결
#include <string>
#include <vector>
#include <algorithm>
#include <string.h>
#include <unordered_map>
using namespace std;
#define ALPHABET_COUNT (26)
class Trie
{
private:
Trie* m_node[ALPHABET_COUNT];
unordered_map<int, int> count;
public:
Trie()
{
memset(this->m_node, NULL, sizeof(this->m_node));
count.clear();
}
~Trie()
{
Clear();
}
void Clear()
{
for (int i = 0; i < ALPHABET_COUNT; i++)
{
if (this->m_node[i])
{
delete this->m_node[i];
}
}
memset(this->m_node, NULL, sizeof(this->m_node));
count.clear();
}
void Insert(const char* key, int keyLength);
Trie* Find(const char* key, int keyLength);
int FindCount(const char* key, int keyLength);
};
void Trie::Insert(const char* key, int keyLength)
{
if (*key == '\0')
{
return;
}
else
{
int index = *key - 'a';
if (this->m_node[index] == NULL)
{
this->m_node[index] = new Trie();
}
if (this->m_node[index]->count.find(keyLength) == this->m_node[index]->count.end())
{
this->m_node[index]->count[keyLength] = 1;
}
else
{
this->m_node[index]->count[keyLength]++;
}
this->m_node[index]->Insert(key + 1, keyLength);
}
}
Trie* Trie::Find(const char* key, int keyLength)
{
if (*key == '\0')
return this;
int index = *key - 'a';
if (this->m_node[index] == NULL)
return NULL;
else
return this->m_node[index]->Find(key + 1, keyLength);
}
int Trie::FindCount(const char* key, int keyLength)
{
Trie *keyTrie = this->Find(key, keyLength);
if (keyTrie == NULL)
return 0;
if (keyTrie->count.find(keyLength) == keyTrie->count.end())
{
return 0;
}
else
{
return keyTrie->count[keyLength];
}
}
vector<int> solution(vector<string> words, vector<string> queries)
{
Trie* forwardTrie = new Trie(), *backwardTrie = new Trie();
for (string word : words)
{
forwardTrie->Insert(word.c_str(), word.length());
string reverseWord = word;
reverse(reverseWord.begin(), reverseWord.end());
backwardTrie->Insert(reverseWord.c_str(), word.length());
}
vector<int> answer;
unordered_map<string, int> allQuestionCase;
for (string query : queries)
{
int count = 0;
if (query[0] == '?')
{
int lastQuestionMarkIndex = query.rfind('?');
string queryWithoutQuestionMark = query.substr(lastQuestionMarkIndex + 1, query.length() - lastQuestionMarkIndex);
if (queryWithoutQuestionMark == "")
{
if (allQuestionCase.find(query) == allQuestionCase.end())
{
for (string word : words)
{
if (word.length() == query.length())
{
count++;
}
}
allQuestionCase[query] = count;
}
else
{
count = allQuestionCase[query];
}
}
else
{
reverse(queryWithoutQuestionMark.begin(), queryWithoutQuestionMark.end());
count = backwardTrie->FindCount(queryWithoutQuestionMark.c_str(), query.length());
}
}
else
{
int firstQuestionMarkIndex = query.find('?');
string queryWithoutQuestionMark = query.substr(0, firstQuestionMarkIndex);
count = forwardTrie->FindCount(queryWithoutQuestionMark.c_str(), query.length());
}
answer.push_back(count);
}
return answer;
}
Leave a comment