刷题的日常-检查单词是否为句中其他单词的前缀

94 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情

刷题的日常-2022年8月21日

一天一题,保持脑子清爽

检查单词是否为句中其他单词的前缀

来自leetcode的 1455 题,题意如下:

给你一个字符串 sentence 作为句子并指定检索词为 searchWord ,其中句子由若干用 单个空格 分隔的单词组成。请你检查检索词 searchWord 是否为句子 sentence 中任意单词的前缀。

如果searchWord 是某一个单词的前缀,则返回句子sentence 中该单词所对应的下标(下标从 1 开始)。如果 searchWord 是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。如果 searchWord 不是任何单词的前缀,则返回 -1 。

字符串 s 的 前缀 是 s 的任何前导连续子字符串。

理解题意

我们可以从题意中提取的条件如下:

  • 题目给定了两个字符串
    • 一个是句子,由空格分隔单词
    • 一个是单词
  • 要求我们找出句子中的由第二个字符串构成前缀的单词
  • 如果有多个,返回索引最小的一个
  • 如果没有,返回-1

做题思路

我们可以暴力用单词一个一个去匹配,最先匹配到的就返回单词的位置,这个很简单,这里提供第二种思路。
前缀树:前缀树是一棵由单词前缀构成的树,树根代表开始位置,我们可以将单词放进树之后再进行匹配。因为要返回最先匹配的单词位置,所以我们放进去之后不需要覆盖原有的前缀:

  • 将句子用 空格 进行切分
  • 构建前缀树,将单词 和 第一次出现的位置放到树中
  • 对查找的单词进行匹配
  • 匹配得到返回位置
  • 否则返回-1

代码实现

代码实现如下:由于要构建前缀树,所以时间复杂度会比较高

public class Solution {
    public int isPrefixOfWord(String sentence, String searchWord) {
        String[] words = sentence.split(" ");
        Tire tire = new Tire(-1);
        for (int i = 0; i < words.length; i++) {
            tire.insert(words[i], i + 1);
        }
        for (int i = 0; i < searchWord.length(); i++) {
            char c = searchWord.charAt(i);
            tire = tire.next[c - 'a'];
            if (tire == null) {
                return -1;
            }
        }
        return tire.idx;
    }
    static class Tire {
        int idx;
        Tire[] next = new Tire[26];
        public Tire(int idx) {
            this.idx = idx;
        }
        public void insert(String word, int idx) {
            Tire tmp = this;
            char c;
            for (int i = 0; i < word.length(); i++) {
                c = word.charAt(i);
                tmp = tmp.next[c - 'a'] = tmp.next[c - 'a'] == null ? new Tire(idx) : tmp.next[c - 'a'];
            }
        }
    }
}

image.png