Post

3376 Longest Common Suffix Queries

3376 Longest Common Suffix Queries

Longest Common Suffix Queries image

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 strings in wordsContainer that share the longest common suffix, find the string that is the smallest in length. If there are two or more such strings that have the same smallest length, find the one that occurred 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].*

 

Example 1:

Input: wordsContainer = [“abcd”,”bcd”,”xbcd”], wordsQuery = [“cd”,”bcd”,”xyz”]

Output: [1,1,1]

Explanation:

Let’s look at each wordsQuery[i] separately:

1
2
3
For wordsQuery[0] = "cd", strings from wordsContainer that share the longest common suffix "cd" are at indices 0, 1, and 2. Among these, the answer is the string at index 1 because it has the shortest length of 3.
For wordsQuery[1] = "bcd", strings from wordsContainer that share the longest common suffix "bcd" are at indices 0, 1, and 2. Among these, the answer is the string at index 1 because it has the shortest length of 3.
For wordsQuery[2] = "xyz", there is no string from wordsContainer that shares a common suffix. Hence the longest common suffix is "", that is shared with strings at index 0, 1, and 2. Among these, the answer is the string at index 1 because it has the shortest length of 3.

Example 2:

Input: wordsContainer = [“abcdefgh”,”poiuygh”,”ghghgh”], wordsQuery = [“gh”,”acbfgh”,”acbfegh”]

Output: [2,0,2]

Explanation:

Let’s look at each wordsQuery[i] separately:

1
2
3
For wordsQuery[0] = "gh", strings from wordsContainer that share the longest common suffix "gh" are at indices 0, 1, and 2. Among these, the answer is the string at index 2 because it has the shortest length of 6.
For wordsQuery[1] = "acbfgh", only the string at index 0 shares the longest common suffix "fgh". Hence it is the answer, even though the string at index 2 is shorter.
For wordsQuery[2] = "acbfegh", strings from wordsContainer that share the longest common suffix "gh" are at indices 0, 1, and 2. Among these, the answer is the string at index 2 because it has the shortest length of 6.

 

Constraints:

1
2
3
4
5
6
7
1 <= wordsContainer.length, wordsQuery.length <= 104
1 <= wordsContainer[i].length <= 5 * 103
1 <= wordsQuery[i].length <= 5 * 103
wordsContainer[i] consists only of lowercase English letters.
wordsQuery[i] consists only of lowercase English letters.
Sum of wordsContainer[i].length is at most 5 * 105.
Sum of wordsQuery[i].length is at most 5 * 105.
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

struct TrieNode {
    children: [Option<Box<TrieNode>>; 26],
    min_len: usize,
    idx: usize,
}

impl TrieNode {
    fn new() -> Self {
        TrieNode {
            children: Default::default(),
            min_len: usize::MAX,
            idx: usize::MAX,
        }
    }
}

struct Trie {
    root: TrieNode,
}

impl Trie {
    fn new() -> Self {
        Trie {
            root: TrieNode::new(),
        }
    }

    fn insert(&mut self, s: &str, idx: usize) {
        let len = s.len();
        let mut node = &mut self.root;

        if len < node.min_len {
            node.min_len = len;
            node.idx = idx;
        }

        for ch in s.chars() {
            let c = (ch as usize) - ('a' as usize);
            if node.children[c].is_none() {
                node.children[c] = Some(Box::new(TrieNode::new()));
            }
            node = node.children[c].as_mut().unwrap();
            
            if len < node.min_len {
                node.min_len = len;
                node.idx = idx;
            }
        }
    }

    fn query(&self, s: &str) -> usize {
        let mut node = &self.root;

        for ch in s.chars() {
            let c = (ch as usize) - ('a' as usize);
            match &node.children[c] {
                Some(next) => node = &**next,
                None => break,
            }
        }

        node.idx
    }
}
impl Solution {
    pub fn string_indices(words_container: Vec<String>, words_query: Vec<String>) -> Vec<i32> {
        let mut trie = Trie::new();

        for (i, word) in words_container.iter().enumerate() {
            let reversed: String = word.chars().rev().collect();
            trie.insert(&reversed, i);
        }

        let mut res = Vec::with_capacity(words_query.len());
        for query in words_query.iter() {
            let reversed: String = query.chars().rev().collect();
            res.push(trie.query(&reversed) as i32);
        }

        res
    }
}



This post is licensed under CC BY 4.0 by the author.