leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

commit 69e611af083aca7118ae10a035e1971440dd440e
parent d8d12c24604d7ac3d5382998cc9550e503726d1e
Author: Jack Sangdahl <jack@pngu.org>
Date:   Thu, 28 May 2026 08:12:29 -0600

3093. longest common suffix queries

Diffstat:
Alongest_common_suffix_queries.c | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alongest_common_suffix_queries.py | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 181 insertions(+), 0 deletions(-)

diff --git a/longest_common_suffix_queries.c b/longest_common_suffix_queries.c @@ -0,0 +1,116 @@ +// 3093. Longest Common Suffix Queries +#include "leetcode.h" + +/* + * you are given two arrays of strings 'wordsContainer' and 'wordsQuery'. for + * each 'wordsQuery[i]', you need to find a string from 'wordsContainer' that + * has the longest common suffix with 'wordsQuery[i]'. if there are two or more + * string in 'wordsContainer' that share the longest common suffix, find the + * string that is the smallest in length. if there are two or more such strigs + * that have the same smallest length, find the one that occured earlier in + * 'wordsContainer'. return an array of integers 'ans' where 'ans[i]' is the + * index of the string in 'wordsContainer' that has the longest common suffix + * with 'wordsQuery[i]'. + */ + +struct trie_node { + struct trie_node *children[26]; + int min_len; + int idx; +}; + +struct trie_node *trie_node_init(void) { + struct trie_node *obj = (struct trie_node *)malloc(sizeof(struct trie_node)); + for (int i = 0; i < 26; i++) + obj->children[i] = NULL; + obj->min_len = obj->idx = INT_MAX; + return obj; +} + +void insert(struct trie_node *root, const char *s, int idx) { + int n = strlen(s); + struct trie_node *node = root; + if (n < node->min_len) { + node->min_len = n; + node->idx = idx; + } + for (int i = 0; i < n; i++) { + int curr = s[i] - 'a'; + if (!node->children[curr]) + node->children[curr] = trie_node_init(); + node = node->children[curr]; + if (n < node->min_len) { + node->min_len = n; + node->idx = idx; + } + } +} + +int query(struct trie_node *root, const char *s) { + int n = strlen(s); + struct trie_node *node = root; + for (int i = 0; i < n; i++) { + int curr = s[i] - 'a'; + if (node->children[curr]) + node = node->children[curr]; + else + break; + } + return node->idx; +} + +void trie_node_free(struct trie_node *obj) { + for (int i = 0; i < 26; i++) + if (obj->children[i]) + trie_node_free(obj->children[i]); + free(obj); +} + +void reverse_string(char *s) { + int n = strlen(s); + for (int i = 0, j = n - 1; i < j; i++, j--) { + char tmp = s[i]; + s[i] = s[j]; + s[j] = tmp; + } +} + +int *stringIndices(char **wordsContainer, int wordsContainerSize, + char **wordsQuery, int wordsQuerySize, int *returnSize) { + struct trie_node *root = trie_node_init(); + for (int i = 0; i < wordsContainerSize; i++) { + reverse_string(wordsContainer[i]); + insert(root, wordsContainer[i], i); + } + int *ans = (int *)malloc(wordsQuerySize * sizeof(int)); + *returnSize = wordsQuerySize; + for (int i = 0; i < wordsQuerySize; i++) { + reverse_string(wordsQuery[i]); + ans[i] = query(root, wordsQuery[i]); + } + trie_node_free(root); + return ans; +} + +int main() { + char *wc1[] = {"abcd", "bcd", "xbcd"}; + char *wq1[] = {"cd", "bcd", "xyz"}; + char *wc2[] = {"abcdefgh", "poiuygh", "ghghgh"}; + char *wq2[] = {"gh", "acbfgh", "acbfegh"}; + int r1[] = {1, 1, 1}, rs1; + int r2[] = {2, 0, 2}, rs2; + int *si1 = stringIndices(wc1, ARRAY_SIZE(wc1), wq1, ARRAY_SIZE(wq1), &rs1); + int *si2 = stringIndices(wc2, ARRAY_SIZE(wc2), wq2, ARRAY_SIZE(wq2), &rs2); + for (int i = 0; i < rs1; i++) { + printf("%d ", si1[i]); + assert(si1[i] == r1[i]); + } + printf("\n"); + for (int i = 0; i < rs2; i++) { + printf("%d ", si2[i]); + assert(si2[i] == r2[i]); + } + printf("\n"); + free(si1); + free(si2); +} diff --git a/longest_common_suffix_queries.py b/longest_common_suffix_queries.py @@ -0,0 +1,65 @@ +# 3093. Longest Common Suffix Queries +from typing import List + +""" +you are given two arrays of strings 'wordsContainer' and 'wordsQuery'. for +each 'wordsQuery[i]', you need to find a string from 'wordsContainer' that +has the longest common suffix with 'wordsQuery[i]'. if there are two or more +string in 'wordsContainer' that share the longest common suffix, find the +string that is the smallest in length. if there are two or more such strigs +that have the same smallest length, find the one that occured earlier in +'wordsContainer'. return an array of integers 'ans' where 'ans[i]' is the +index of the string in 'wordsContainer' that has the longest common suffix +with 'wordsQuery[i]'. +""" + + +class trie_node: + def __init__(self): + self.children = {} + self.min_len = float("inf") + self.idx = float("inf") + + +class Solution: + def stringIndices( + self, wordsContainer: List[str], wordsQuery: List[str] + ) -> List[int]: + root = trie_node() + for i, word in enumerate(wordsContainer): + n = len(word) + curr = root + if n < curr.min_len or (n == curr.min_len and i < curr.idx): + curr.min_len = n + curr.idx = i + for char in reversed(word): + if char not in curr.children: + curr.children[char] = trie_node() + curr = curr.children[char] + if n < curr.min_len or (n == curr.min_len and i < curr.idx): + curr.min_len = n + curr.idx = i + ans = [] + for query in wordsQuery: + curr = root + for char in reversed(query): + if char not in curr.children: + break + curr = curr.children[char] + ans.append(curr.idx) + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.stringIndices( + wordsContainer=["abcd", "bcd", "xbcd"], wordsQuery=["cd", "bcd", "xyz"] + ) + ) + print( + obj.stringIndices( + wordsContainer=["abcdefgh", "poiuygh", "ghghgh"], + wordsQuery=["gh", "acbfgh", "acbfegh"], + ) + )