bluecode-SQL代码补全功能

70 阅读3分钟

问题描述

在开发SQL编辑器时,实现自动补全功能是提高用户体验的重要一环。小C需要实现一个功能,根据用户输入的字符片段,快速从已知的SQL关键字和数据库相关名称中找到所有以该片段开头的候选词,并按字典序输出。

例如,当用户输入 s 时,编辑器需要自动提示以 s 开头的所有可能选项,如 select。如果用户输入 fr,则需要提示 from 和 from_mobile。如果在提示中只有一个选项符合,如输入 from_ 时只提示 from_mobile


测试样例

样例1:

输入:num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "f"
输出:'from,from_mobile'

样例2:

输入:num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "wh"
输出:'where'

样例3:

输入:num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "z"
输出:'-1'

样例4:

输入:num = 8,data = ["select", "from", "where", "limit", "origin_log_db", "event_log_table", "user_id", "from_mobile"], input = "origin"
输出:'origin_log_db'

#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>

std::string solution(int num, std::vector<std::string> data,
                     std::string input) {
  std::vector<std::string> res;
  std::unordered_set<std::string> repeat;

  // 遍历 data 数组,查找以 input 开头的字符串
  for (int i = 0; i < num; ++i) {
    if (data[i].find(input) == 0) { // 检查是否以 input 开头
      if (repeat.find(data[i]) == repeat.end()) {
        res.push_back(data[i]);
        repeat.insert(data[i]);
      }
    }
  }

  // 如果没有符合条件的候选词,返回 "-1"
  if (res.empty()) {
    return "-1";
  } else if (res.size() == 1) {
    // 如果只有一个候选词,直接返回该候选词
    return res[0];
  } else {
    // 如果有多个候选词,按字典序排序后,使用逗号连接并返回
    std::sort(res.begin(), res.end());
    std::string result = res[0];
    for (size_t i = 1; i < res.size(); ++i) {
      result += "," + res[i];
    }
    return result;
  }
}

int main() {
  //  You can add more test cases here
  std::vector<std::string> testData1 = {
      "select",          "from",    "where",      "limit", "origin_log_db",
      "event_log_table", "user_id", "from_mobile"};

  std::cout << (solution(8, testData1, "f") == "from,from_mobile") << std::endl;
  std::cout << (solution(8, testData1, "wh") == "where") << std::endl;
  std::cout << (solution(8, testData1, "z") == "-1") << std::endl;

  return 0;
}

前缀树

#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

class Trie {
private:
  struct TrieNode {
    bool isEnd;
    std::unordered_map<char, TrieNode *> children;
    TrieNode() : isEnd(false) {}
  };

  TrieNode *root;

public:
  Trie() { root = new TrieNode(); }

  void insert(const std::string &word) {
    TrieNode *node = root;
    for (char ch : word) {
      if (!node->children.count(ch)) {
        node->children[ch] = new TrieNode();
      }
      node = node->children[ch];
    }
    node->isEnd = true;
  }

  void findWords(TrieNode *node, const std::string &prefix,
                 std::vector<std::string> &results) {
    if (!node)
      return;
    if (node->isEnd)
      results.push_back(prefix);

    for (auto &[ch, child] : node->children) {
      findWords(child, prefix + ch, results);
    }
  }

  std::vector<std::string> searchWithPrefix(const std::string &prefix) {
    TrieNode *node = root;
    for (char ch : prefix) {
      if (!node->children.count(ch))
        return {}; // 直接返回空
      node = node->children[ch];
    }
    std::vector<std::string> results;
    findWords(node, prefix, results);
    return results;
  }
};

std::string solution(int num, const std::vector<std::string> &data,
                     const std::string &input) {
  Trie trie;
  std::unordered_set<std::string> uniqueWords;

  // 插入数据到 Trie,并去重
  for (const auto &word : data) {
    if (uniqueWords.insert(word).second) {
      trie.insert(word);
    }
  }

  // 查找匹配的前缀
  std::vector<std::string> res = trie.searchWithPrefix(input);
  if (res.empty())
    return "-1";

  // 按字典序排序并拼接结果
  std::sort(res.begin(), res.end());
  return std::accumulate(
      res.begin() + 1, res.end(), res[0],
      [](const std::string &a, const std::string &b) { return a + "," + b; });
}

int main() {
  //  You can add more test cases here
  std::vector<std::string> testData1 = {
      "select",          "from",    "where",      "limit", "origin_log_db",
      "event_log_table", "user_id", "from_mobile"};

  std::cout << (solution(8, testData1, "f") == "from,from_mobile") << std::endl;
  std::cout << (solution(8, testData1, "wh") == "where") << std::endl;
  std::cout << (solution(8, testData1, "z") == "-1") << std::endl;

  return 0;
}