当前位置: 首页 > news >正文

剑指 Offer II 063. 替换单词


comments: true
edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20063.%20%E6%9B%BF%E6%8D%A2%E5%8D%95%E8%AF%8D/README.md

剑指 Offer II 063. 替换单词

题目描述

在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典和一个句子,需要将句子中的所有继承词词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

需要输出替换之后的句子。

 

示例 1:

输入:dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"

示例 2:

输入:dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
输出:"a a b c"

示例 3:

输入:dictionary = ["a", "aa", "aaa", "aaaa"], sentence = "a aa a aaaa aaa aaa aaa aaaaaa bbb baba ababa"
输出:"a a a a a a a a bbb baba a"

示例 4:

输入:dictionary = ["catt","cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"

示例 5:

输入:dictionary = ["ac","ab"], sentence = "it is abnormal that this solution is accepted"
输出:"it is ab that this solution is ac"

 

提示:

  • 1 <= dictionary.length <= 1000
  • 1 <= dictionary[i].length <= 100
  • dictionary[i] 仅由小写字母组成。
  • 1 <= sentence.length <= 10^6
  • sentence 仅由小写字母和空格组成。
  • sentence 中单词的总量在范围 [1, 1000] 内。
  • sentence 中每个单词的长度在范围 [1, 1000] 内。
  • sentence 中单词之间由一个空格隔开。
  • sentence 没有前导或尾随空格。

 

注意:本题与主站 648 题相同: https://leetcode.cn/problems/replace-words/

解法

方法一:哈希表

Python3
class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        dic=set(dictionary)
        
        # 查最短词根
        words=sentence.split()
        for i,w in enumerate(words):
            for j in range(1,len(w)+1):
                if w[:j] in dic: #寻最短前缀词根
                    words[i]=w[:j]
                    break
        return ' '.join(words)
Java
class Solution {
    public String replaceWords(List<String> dictionary, String sentence) {
        Set<String> s = new HashSet<>(dictionary);
        String[] words = sentence.split(" ");
        for (int i = 0; i < words.length; ++i) {
            String word = words[i];
            for (int j = 1; j <= word.length(); ++j) {
                String t = word.substring(0, j);
                if (s.contains(t)) {
                    words[i] = t;
                    break;
                }
            }
        }
        return String.join(" ", words);
    }
}
C++
class Solution {
public:
    string replaceWords(vector<string>& dictionary, string sentence) {
        unordered_set<string> s(dictionary.begin(), dictionary.end());
        istringstream is(sentence);
        vector<string> words;
        string ss;
        while (is >> ss) words.push_back(ss);
        for (int i = 0; i < words.size(); ++i) {
            string word = words[i];
            for (int j = 1; j <= word.size(); ++j) {
                string t = word.substr(0, j);
                if (s.count(t)) {
                    words[i] = t;
                    break;
                }
            }
        }
        string ans = "";
        for (string& word : words) ans += word + " ";
        ans.pop_back();
        return ans;
    }
};
Go
func replaceWords(dictionary []string, sentence string) string {
	s := map[string]bool{}
	for _, v := range dictionary {
		s[v] = true
	}
	words := strings.Split(sentence, " ")
	for i, word := range words {
		for j := 1; j <= len(word); j++ {
			t := word[:j]
			if s[t] {
				words[i] = t
				break
			}
		}
	}
	return strings.Join(words, " ")
}
Swift
class Solution {
    func replaceWords(_ dictionary: [String], _ sentence: String) -> String {
        let dictSet = Set(dictionary)
        var words = sentence.split(separator: " ").map { String($0) }

        for i in 0..<words.count {
            let word = words[i]
            for j in 1...word.count {
                let prefix = String(word.prefix(j))
                if dictSet.contains(prefix) {
                    words[i] = prefix
                    break
                }
            }
        }

        return words.joined(separator: " ")
    }
}

方法二:前缀树【空间换时间,时间复杂度降低一个量级】

Python3
class Trie:
    def __init__(self):
        self.children=[None]*26 #多叉树:每一层节点索引代表一个字母 # word 和 prefix 仅由小写英文字母组成
        self.is_end=None

    def insert(self, word: str) -> None:
        Node=self #__init__
        for w in word:
            idx=ord(w)-ord("a")
            if not Node.children[idx]:
                Node.children[idx]=Trie()
            Node=Node.children[idx]
        Node.is_end=word #两个作用


    def search(self, prefix: str) -> bool:
        root = self
        for c in prefix:
            idx = ord(c) - ord("a")
            if not root.children[idx]: #1无对应词根,返回原单词
                return prefix

            root = root.children[idx] #2有对应词根,及时返回最短词根
            if root.is_end:return root.is_end

        return prefix

class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        # 建立“词根前缀树”
        tr=Trie()
        for dic in dictionary:
            tr.insert(dic)

        # 查最短词根
        words=sentence.split()
        return ' '.join(tr.search(w) for w in words)
Java
class Trie {
    Trie[] children = new Trie[26];
    String v;

    void insert(String word) {
        Trie node = this;
        for (char c : word.toCharArray()) {
            c -= 'a';
            if (node.children[c] == null) {
                node.children[c] = new Trie();
            }
            node = node.children[c];
        }
        node.v = word;
    }

    String search(String word) {
        Trie node = this;
        for (char c : word.toCharArray()) {
            c -= 'a';
            if (node.children[c] == null) {
                return word;
            }
            node = node.children[c];
            if (node.v != null) {
                return node.v;
            }
        }
        return word;
    }
}

class Solution {
    public String replaceWords(List<String> dictionary, String sentence) {
        Trie trie = new Trie();
        for (String v : dictionary) {
            trie.insert(v);
        }
        List<String> ans = new ArrayList<>();
        for (String v : sentence.split("\\s")) {
            ans.add(trie.search(v));
        }
        return String.join(" ", ans);
    }
}
C++
class Trie {
public:
    vector<Trie*> children;
    string v;
    Trie()
        : children(26)
        , v("") {}

    void insert(string word) {
        Trie* node = this;
        for (char c : word) {
            c -= 'a';
            if (!node->children[c]) node->children[c] = new Trie();
            node = node->children[c];
        }
        node->v = word;
    }

    string search(string word) {
        Trie* node = this;
        for (char c : word) {
            c -= 'a';
            if (!node->children[c]) break;
            node = node->children[c];
            if (node->v != "") return node->v;
        }
        return word;
    }
};

class Solution {
public:
    string replaceWords(vector<string>& dictionary, string sentence) {
        Trie* trie = new Trie();
        for (auto& v : dictionary) trie->insert(v);
        string ans = "";
        istringstream is(sentence);
        vector<string> ss;
        string s;
        while (is >> s) ss.push_back(s);
        for (auto word : ss) ans += trie->search(word) + " ";
        ans.pop_back();
        return ans;
    }
};
Go
type Trie struct {
	children [26]*Trie
	v        string
}

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

func (this *Trie) search(word string) string {
	node := this
	for _, c := range word {
		c -= 'a'
		if node.children[c] == nil {
			break
		}
		node = node.children[c]
		if node.v != "" {
			return node.v
		}
	}
	return word
}

func replaceWords(dictionary []string, sentence string) string {
	trie := newTrie()
	for _, v := range dictionary {
		trie.insert(v)
	}
	var ans []string
	for _, v := range strings.Split(sentence, " ") {
		ans = append(ans, trie.search(v))
	}
	return strings.Join(ans, " ")
}
http://www.dtcms.com/a/59894.html

相关文章:

  • 计算机视觉算法实战——老虎个体识别(主页有源码)
  • Python中的装饰器(Decorator) 详解
  • 六十天前端强化训练之第十二天之闭包深度解析
  • 【RK3588嵌入式图形编程】-SDL2-SDL_Image使用详解
  • 3D空间曲线批量散点化软件V1.0正式发布,将空间线条导出坐标点,SolidWorks/UG/Catia等三维软件通用
  • 为什么 MySQL InnoDB 的 Repeatable Read 可以阻止幻读?
  • Django工程获取请求参数的几种方式
  • 一遍通俗易懂的新华三交换机文档指南操作手册
  • AI日报 - 2025年3月10日
  • [项目]基于FreeRTOS的STM32四轴飞行器: 六.2.4g通信
  • ArduPilot开源代码之AP_OSD
  • 基于Python的商品销量的数据分析及推荐系统
  • 使用 Docker 部署 GitLab 并持久化数据
  • comctl32!ListView_OnSetItem函数分析LISTSUBITEM结构中的image表示图标位置
  • 简单的 Python 示例,用于生成电影解说视频的第一人称独白解说文案
  • Oracle数据库监听学习
  • NoteGen是一款开源跨平台的 AI 笔记应用,专注于 recording 和 writing ,基于 Tauri 开发
  • Node.js 技术原理分析系列 4—— 使用 Chrome DevTools 分析 Node.js 性能问题
  • IMX6ULL驱动开发Linux篇02——移植Rootfs
  • 李沐《动手学深度学习》——14.9. 用于预训练BERT的数据集——wiki数据集问题以及存在的其他问题
  • 小白学习:rag向量数据库
  • 《C++ primer》第四章
  • FOC 控制笔记【二】无感控制、滑膜观测器和PLL
  • 用《设计模式》的角度优化 “枚举”
  • Python零基础学习第三天:函数与数据结构
  • PyTorch深度学习在硬件与资源限制下分布式训练和多GPU加速等技术的实例代码
  • 从零构建高可用MySQL自动化配置系统:核心技术、工具开发与企业级最佳实践
  • Linux 指定命令行前后添加echo打印内容
  • Unity URP渲染管线烘焙场景教程
  • docker装Oracle