function solution(words, queries) {
const getCodeFrom = (str, i) => str[i].charCodeAt() - 97;
const tries = {};
const count = Array(26).fill(0);
const isAllPossible = (str) => str[0] === '?' && str[str.length - 1] === '?';
function Node(weight = 0) {
this.weight = weight;
this.children = Array(26).fill(0);
}
const insertWord = (word, reverse) => {
let trie;
if (tries[word.length]) {
trie = tries[word.length];
} else {
tries[word.length] = {
forward: Array(26)
.fill(0)
.map((c) => new Node()),
reverse: Array(26)
.fill(0)
.map((c) => new Node()),
};
trie = tries[word.length];
}
let parent = reverse
? trie.reverse[getCodeFrom(word, word.length - 1)]
: trie.forward[getCodeFrom(word, 0)];
parent.weight += 1;
for (let i = 1; i < word.length; i++) {
const code = getCodeFrom(word, reverse ? word.length - 1 - i : i);
let current = parent.children[code];
if (current) {
current.weight += 1;
} else {
current = new Node(1);
parent.children[code] = current;
}
parent = current;
}
};
const getWeight = (query) => {
if (!tries[query.length]) {
return 0;
}
const trie = tries[query.length];
const isReverse = query[0] === '?' ? true : false;
let current = isReverse ? query.length - 1 : 0;
let parent = isReverse
? trie.reverse[getCodeFrom(query, current)]
: trie.forward[getCodeFrom(query, current)];
while (parent) {
isReverse ? current-- : current++;
if (query[current] === '?') {
return parent.weight;
}
parent = parent.children[getCodeFrom(query, current)];
}
return 0;
};
words.forEach((word) => {
count[word.length] = count[word.length] ? count[word.length] + 1 : 1;
insertWord(word);
insertWord(word, 'reverse');
});
return queries.map((query) => {
if (isAllPossible(query)) {
return count[query.length];
}
return getWeight(query);
});
}
function solution(words, queries) {
var answer = [];
function TrieNode(){
this.children = {};
this.weight = 0;
}
function Trie(isReverse){
this.head = Array(10000).fill(0);
this.append = word => {
if(!this.head[word.length]){
this.head[word.length] = {
children:{},
weight:0,
}
}
let parent = this.head[word.length]
parent.weight += 1;
for(let i=0; i<word.length; i++){
const c = word[i]
if(!parent.children[c]){
parent.children[c] = new TrieNode()
}
parent.children[c].weight+=1;
parent = parent.children[c];
}
}
this.search = (word) => {
let parent = this.head[word.length];
if(!parent){
return 0;
}
for(let i=0; i<word.length; i++){
const c = word[i]
if(c==='?') return parent.weight;
parent = parent.children[c]
if(!parent) return 0
}
return parent.weight;
}
}
const forwardTrie = new Trie()
const reverseTrie = new Trie()
words.forEach(word =>{
forwardTrie.append(word)
reverseTrie.append(word.split('').reverse().join(''))
})
queries.forEach(query => {
if(query[query.length-1] ==='?') return answer.push(forwardTrie.search(query))
answer.push(reverseTrie.search(query.split('').reverse().join('')))
})
return answer;
}