【动态规划算法题记录】NV某笔试题目(哈希+dp)

最长字符串链(String Chains)

题目描述

给定一个表示字典的单词数组,测试每个单词,查看它是否可以通过逐一去除字符变为字典中的另一个单词。每个单词代表其字符串链的第一个元素,因此字符串链的初始长度为1。每次去除一个字符时,将字符串链的长度增加1。为了移除一个字符,生成的单词必须在原始字典中。确定给定字典可以实现的最长字符串链。

示例

bash 复制代码
n = 4
words = ['a', 'and', 'an', 'bear']

单词 and 可以被简化为 an,然后再简化为 a。字符 a 不能再进一步简化,因为字典中没有空字符串。单词 bear 无法简化。最长的字符串链长度为 3。

longestChain 有以下参数:

int n:单词数组的长度

str words[n]:要测试的字符串字典

返回值:

int:最长字符串链的长度

约束条件
1 ≤ n ≤ 50000
1 ≤ |words[i]| ≤ 60,其中 0 ≤ i < n

每个 words[i] 由范围 ascii[a-z] 的小写字母组成

输入格式:

第一行包含一个整数 n,表示 words 数组的大小。

接下来的 n 行中,每行包含一个值 words[i],其中 0 ≤ i < n。

示例案例 0
输入:

bash 复制代码
6
a
b
ba
bca
bda
bdca

输出:

bash 复制代码
4

解释:

words = ["a", "b", "ba", "bca", "bda", "bdca"]

由于 a 和 b 是单字符单词,它们不能被简化。这会导致空字符串,因此它们的字符串链长度为 1。

单词 ba 可以创建两个不同的字符串链,每个长度为 2:("ba"→ "a" 和 "ba"→ "b")。此时当前最长字符串链长度为 2。

单词 bca 可以创建两个不同的字符串链,每个长度为 3:("bca"→ "ba"→ "a" 和 "bca"→ "ba"→ "b")。此时当前最长字符串链长度为 3。

单词 bda 可以创建两个不同的字符串链,每个长度为 3:("bda"→ "ba"→ "a" 和 "bda"→ "ba"→ "b")。此时当前最长字符串链长度仍然为 3。

单词 bdca 可以创建四个不同的字符串链,每个长度为 4:("bdca"→ "bda"→ "ba"→ "a","bdca"→ "bca"→ "ba"→ "b","bdca"→ "bda"→ "ba"→ "b")。当前最长字符串链长度为 4。

最长字符串链的长度为 4。

思路分析

哈希表+dp:

  1. 哈希表存放字典中的每个单词的字符串链数量,初始都为1。
  2. 将字典按照字符个数从小到大排列
  3. dp[i]是第i个单词的最长字符串链数量,递推公式 dp["abc"] = dp["ab"] + dp["ac"] + dp["bc"]。具体见代码。

cpp代码

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

string ltrim(const string &);
string rtrim(const string &);

#include <unordered_map>
/*
 * Complete the 'longestChain' function below.
 *
 * The function is expected to return an INTEGER.
 * The function accepts STRING_ARRAY words as parameter.
 */

int longestChain(vector<string> words) {
    // 对words单词长短进行排序
    sort(words.begin(), words.end(), [](const string& a, const string& b){
        return a.length() < b.length();
    });
    int ans = 1;
    // dp["abc"]:字符串abc的最长字符链
    // 递推公式 dp["abc"] = dp["ab"] + dp["ac"] + dp["bc"]
    unordered_map<string, int> dp; // key:字典中的单词,value:出现次数
    for(const string& s : words){
        dp[s] = 1;
        for(int i = 0; i < s.size(); ++i){
            string subs = s.substr(0, i) + s.substr(i+1);
            if(dp.find(subs) != dp.end()){
                dp[s] = max(dp[s], dp[subs] + 1);
            }
        }
        ans = max(ans, dp[s]);
    }
    return ans;
}

int main()
{
    ofstream fout(getenv("OUTPUT_PATH"));

    string words_count_temp;
    getline(cin, words_count_temp);

    int words_count = stoi(ltrim(rtrim(words_count_temp)));

    vector<string> words(words_count);

    for (int i = 0; i < words_count; i++) {
        string words_item;
        getline(cin, words_item);

        words[i] = words_item;
    }

    int result = longestChain(words);

    fout << result << "\n";

    fout.close();

    return 0;
}

string ltrim(const string &str) {
    string s(str);

    s.erase(
        s.begin(),
        find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace)))
    );

    return s;
}

string rtrim(const string &str) {
    string s(str);

    s.erase(
        find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(),
        s.end()
    );

    return s;
}

总结

总体来说nv的难度没有特别难,但是英文看着好吃力。。。QAQ

相关推荐
嘉陵妹妹1 小时前
深度优先算法学习
学习·算法·深度优先
GalaxyPokemon2 小时前
LeetCode - 53. 最大子数组和
算法·leetcode·职场和发展
hn小菜鸡2 小时前
LeetCode 1356.根据数字二进制下1的数目排序
数据结构·算法·leetcode
zhuiQiuMX2 小时前
分享今天做的力扣SQL题
sql·算法·leetcode
music&movie3 小时前
算法工程师认知水平要求总结
人工智能·算法
laocui14 小时前
Σ∆ 数字滤波
人工智能·算法
yzx9910134 小时前
Linux 系统中的算法技巧与性能优化
linux·算法·性能优化
全栈凯哥5 小时前
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
java·算法·leetcode·链表
全栈凯哥5 小时前
Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解
java·算法·leetcode·链表
SuperCandyXu5 小时前
leetcode2368. 受限条件下可到达节点的数目-medium
数据结构·c++·算法·leetcode