📜  门|门CS 2010 |第 35 题(1)

📅  最后修改于: 2023-12-03 15:12:47.185000             🧑  作者: Mango

题目介绍

题目描述

给定一个字符串 s 和一个字符串列表 dict ,你需要将所有在字符串列表中出现过的 s 的子串替换为 "*" 。

示例

输入:

s = "leetcode"
dict = ["leet", "code"]

输出:

"*****ode"
提示
  • 0 <= len(s) <= 1000
  • 0 <= len(dict) <= 100
  • 0 <= len(dict[i]) <= 100
题目分析

本题的基本思路是,遍历字符串列表dict,对于每个字符串,判断其是否是s的子串。如果是,则将其替换为"***"。

具体实现有多种方式,例如暴力枚举、Trie树等。在本文中,我们将介绍一种基于Trie树的解法。

代码实现
Python
from typing import List

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word: str) -> None:
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.isEnd = True
        
    def search(self, word: str) -> bool:
        node = self.root
        for c in word:
            if c not in node.children:
                return False
            node = node.children[c]
        return node.isEnd

class Solution:
    def replaceWords(self, dict: List[str], s: str) -> str:
        trie = Trie()
        for word in dict:
            trie.insert(word)
        words = s.split()
        res = []
        for word in words:
            for i in range(len(word)):
                if trie.search(word[:i]):
                    res.append("*" * len(word))
                    break
            else:
                res.append(word)
        return " ".join(res)
Java
class TrieNode {
    Map<Character, TrieNode> children;
    boolean isEnd;
    
    public TrieNode() {
        children = new HashMap<>();
        isEnd = false;
    }
}

class Trie {
    TrieNode root;
    
    public Trie() {
        root = new TrieNode();
    }
    
    public void insert(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (!node.children.containsKey(c)) {
                node.children.put(c, new TrieNode());
            }
            node = node.children.get(c);
        }
        node.isEnd = true;
    }
    
    public boolean search(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (!node.children.containsKey(c)) {
                return false;
            }
            node = node.children.get(c);
            if (node.isEnd) {
                return true;
            }
        }
        return false;
    }
}

class Solution {
    public String replaceWords(List<String> dict, String s) {
        Trie trie = new Trie();
        for (String word : dict) {
            trie.insert(word);
        }
        String[] words = s.split("\\s+");
        StringBuilder sb = new StringBuilder();
        for (String word : words) {
            boolean flag = false;
            StringBuilder temp = new StringBuilder();
            for (int i = 1; i <= word.length(); i++) {
                String prefix = word.substring(0, i);
                if (trie.search(prefix)) {
                    temp.append("*".repeat(word.length()));
                    flag = true;
                    break;
                } else {
                    temp.append(word.charAt(i - 1));
                }
            }
            if (!flag) {
                temp.append(word);
            }
            sb.append(temp.toString() + " ");
        }
        return sb.toString().trim();
    }
}
总结

本题重点在于如何快速判断一个字符串是否是另一个字符串的前缀。可以使用Trie树进行优化。时间复杂度为O(NM),其中N为字符串s的长度,M为字符串列表dict中所有字符串的长度和。