最长字符串链(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。
- 将字典按照字符个数从小到大排列
- 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