跳转至

2185. 统计包含给定前缀的字符串

题目描述

给你一个字符串数组 words 和一个字符串 pref

返回 words 中以 pref 作为 前缀 的字符串的数目。

字符串 s前缀 就是  s 的任一前导连续字符串。

 

示例 1:

输入:words = ["pay","attention","practice","attend"], pref = "at"
输出:2
解释:以 "at" 作为前缀的字符串有两个,分别是:"attention" 和 "attend" 。

示例 2:

输入:words = ["leetcode","win","loops","success"], pref = "code"
输出:0
解释:不存在以 "code" 作为前缀的字符串。

 

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length, pref.length <= 100
  • words[i]pref 由小写英文字母组成

解法

方法一:一次遍历

根据题目描述,我们遍历字符串数组 words 中的每个字符串 $w$,判断其是否以 $pref$ 作为前缀,如果是,则答案加一。

时间复杂度 $O(n \times m)$,空间复杂度 $O(1)$。其中 $n$ 和 $m$ 分别是字符串数组 words 和字符串 $pref$ 的长度。

1
2
3
class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        return sum(w.startswith(pref) for w in words)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution {
    public int prefixCount(String[] words, String pref) {
        int ans = 0;
        for (String w : words) {
            if (w.startsWith(pref)) {
                ++ans;
            }
        }
        return ans;
    }
}
1
2
3
4
5
6
7
8
class Solution {
public:
    int prefixCount(vector<string>& words, string pref) {
        int ans = 0;
        for (auto& w : words) ans += w.find(pref) == 0;
        return ans;
    }
};
1
2
3
4
5
6
7
8
func prefixCount(words []string, pref string) (ans int) {
    for _, w := range words {
        if strings.HasPrefix(w, pref) {
            ans++
        }
    }
    return
}
1
2
3
function prefixCount(words: string[], pref: string): number {
    return words.reduce((r, s) => (r += s.startsWith(pref) ? 1 : 0), 0);
}
1
2
3
4
5
6
7
8
impl Solution {
    pub fn prefix_count(words: Vec<String>, pref: String) -> i32 {
        words
            .iter()
            .filter(|s| s.starts_with(&pref))
            .count() as i32
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int prefixCount(char** words, int wordsSize, char* pref) {
    int ans = 0;
    int n = strlen(pref);
    for (int i = 0; i < wordsSize; i++) {
        if (strncmp(words[i], pref, n) == 0) {
            ans++;
        }
    }
    return ans;
}

方法二:前缀树

我们还可以使用前缀树来查询答案。

定义前缀树的每个节点结构如下:

  • children:长度为 $26$ 的数组,用于存储当前节点的所有子节点,其中 children[i] 表示当前节点的子节点;
  • cnt:所有以当前节点为前缀的字符串的数量。

另外,我们还需要定义两个函数:

  • 其中一个函数 $insert(w)$ 用于将字符串 $w$ 插入前缀树中;
  • 另一个函数 $search(pref)$ 用于查询以字符串 $pref$ 作为前缀的字符串的数量。查询时,我们从前缀树的根节点开始,遍历字符串 $pref$,如果当前节点的子节点中不存在 $pref[i]$,则说明 $pref$ 不是任何字符串的前缀,直接返回 $0$。否则,我们继续遍历 $pref$ 的下一个字符,直到遍历完 $pref$,返回当前节点的 cnt 即可。

有了上述函数,我们就可以查询答案了。

遍历字符串数组 words,对于每个字符串 $w$,调用 $insert(w)$ 函数将其插入前缀树中。最后调用 $search(pref)$ 函数作为答案返回即可。

时间复杂度 $O(L)$,空间复杂度 $O(L)$。其中 $L$ 是字符串数组 words 中所有字符串的长度之和。

 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
class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.cnt = 0

    def insert(self, w):
        node = self
        for c in w:
            i = ord(c) - ord('a')
            if node.children[i] is None:
                node.children[i] = Trie()
            node = node.children[i]
            node.cnt += 1

    def search(self, pref):
        node = self
        for c in pref:
            i = ord(c) - ord('a')
            if node.children[i] is None:
                return 0
            node = node.children[i]
        return node.cnt


class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        tree = Trie()
        for w in words:
            tree.insert(w)
        return tree.search(pref)
 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
class Trie {
    private Trie[] children = new Trie[26];
    private int cnt;

    public void insert(String w) {
        Trie node = this;
        for (int i = 0; i < w.length(); ++i) {
            int j = w.charAt(i) - 'a';
            if (node.children[j] == null) {
                node.children[j] = new Trie();
            }
            node = node.children[j];
            ++node.cnt;
        }
    }

    public int search(String pref) {
        Trie node = this;
        for (int i = 0; i < pref.length(); ++i) {
            int j = pref.charAt(i) - 'a';
            if (node.children[j] == null) {
                return 0;
            }
            node = node.children[j];
        }
        return node.cnt;
    }
}

class Solution {
    public int prefixCount(String[] words, String pref) {
        Trie tree = new Trie();
        for (String w : words) {
            tree.insert(w);
        }
        return tree.search(pref);
    }
}
 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
class Trie {
public:
    Trie()
        : children(26)
        , cnt(0) {}

    void insert(string w) {
        Trie* node = this;
        for (auto& c : w) {
            int i = c - 'a';
            if (!node->children[i]) {
                node->children[i] = new Trie();
            }
            node = node->children[i];
            ++node->cnt;
        }
    }

    int search(string pref) {
        Trie* node = this;
        for (auto& c : pref) {
            int i = c - 'a';
            if (!node->children[i]) {
                return 0;
            }
            node = node->children[i];
        }
        return node->cnt;
    }

private:
    vector<Trie*> children;
    int cnt;
};

class Solution {
public:
    int prefixCount(vector<string>& words, string pref) {
        Trie* tree = new Trie();
        for (auto& w : words) {
            tree->insert(w);
        }
        return tree->search(pref);
    }
};
 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
type Trie struct {
    children [26]*Trie
    cnt      int
}

func newTrie() *Trie {
    return &Trie{}
}

func (this *Trie) insert(w string) {
    node := this
    for _, c := range w {
        c -= 'a'
        if node.children[c] == nil {
            node.children[c] = newTrie()
        }
        node = node.children[c]
        node.cnt++
    }
}

func (this *Trie) search(pref string) int {
    node := this
    for _, c := range pref {
        c -= 'a'
        if node.children[c] == nil {
            return 0
        }
        node = node.children[c]
    }
    return node.cnt
}

func prefixCount(words []string, pref string) int {
    tree := newTrie()
    for _, w := range words {
        tree.insert(w)
    }
    return tree.search(pref)
}

评论