安吉D9-T3
944 字
5 分钟
安吉D9-T3
- 1安吉D19 T1
- 2安吉D19 T3
- 3安吉D20 模考12总结
- 4安吉D17 T3
- 5安吉D17 T4
- 6安吉D19 模考11总结
- 7安吉D15 A
- 8安吉D16 T4
- 9安吉D17 T1
- 10安吉D17 模考10总结
- 11安吉D16 T3
- 12安吉D16 模考9总结
- 13安吉D13 模考8总结
- 14安吉D13-T2
- 15安吉D13-T3
- 16安吉D12-T3
- 17安吉D11-B
- 18安吉D11-C
- 19安吉D11-D
- 20安吉D12 模考7总结
- 21安吉D12-T2
- 22安吉D11-A
- 23安吉D10 模考6总结
- 24安吉D10-T3
- 25安吉D10-T4
- 26安吉D8-E
- 27安吉D9-T4
- 28安吉D8-A
- 29安吉D8-B
- 30安吉D8-C
- 31安吉D8-D
- 32安吉D9 模考5总结
- 33安吉D9-T2
- 34安吉D9-T3本文
- 35安吉D6-T4
- 36安吉D4-G
- 37安吉D5-T2
- 38安吉D6 模考4总结
- 39安吉D6-T1
- 40安吉D6-T3
- 41安吉-开营测试 T4
- 42安吉D5 模考3总结
- 43安吉D5-T3
- 44安吉D4-A
- 45安吉D4-B
- 46安吉D4-C
- 47安吉D4:容斥原理
- 48安吉Day4-D
- 49安吉D3 模考2总结
- 50安吉D3-T1
- 51安吉D3-T2
- 52安吉D3-T4
- 53安吉D2 模考1总结
- 54安吉D2-T2
- 55安吉D1-G
- 56安吉D1-L
- 57安吉D2-T4
原题呈现
P1688 新单词接龙问题
题目描述
给定一个包含 个单词的字典,定义字典序为单词在这本字典的顺序.从中选择若干个单词,按字典序进行单词接龙,使得接龙的长度最大.
新单词接龙的规则:
- 单词变换:单词 添加一个字母,删除一个字母,或修改一个字母可以得到单词 ;
- 字典序接龙:,满足字典序.
输入格式
第一行一个整数 (),表示字典中单词的总数.接下来 行,按字典序输入 个单词,每行一个字符串,表示单词,单词仅由小写字母组成,长度在 至 以内.
输出格式
输出一行一个整数,表示能获得的单词接龙的最大长度.
输入输出样例 #1
输入 #1
9catdigdogfigfinfinefoglogwine输出 #1
5说明/提示
样例解释
长度为 的单词接龙为:.
此题动态规划.类似最长上升子序列问题,定义 f[n] 表示以 结尾的字符串最长的接龙长度.
观察到字符串的长度很小,远小于 .因此,对于此题,我们在转移时不选择枚举之前的所有字符串,而是选择枚举所有能够通过一次修改转移到当前字符串的前置字符串.具体来说:
- 枚举每一个字符串 ,在枚举时,遍历所有可能的前置字符串(相对 多一个字符、少一个字符、改一个字符),并在前面所有枚举过的给定字符串中查找,如果存在这样的前置字符串 ,则说明 可以接在 后面,可以转移:将
f[i] = f[j] + 1.
这样的算法枚举前置字符串的复杂度为 ,每一次比较是 ,总复杂度是 的,.
考虑优化枚举前面的字符串,可以使用 unordered_map 存储前面所有遍历过的给定字符串对应的 f 值,直接在 中查找,这样的时间复杂度是 的.
考虑使用哈希优化,这样判断两个字符串相等就可以在 的复杂度内完成,时间复杂度 .
由于此题字符串比较多,推荐使用 unsigned long long 自然溢出来实现哈希,不易冲突的同时且能够做到时间常数较小.
#include <bits/stdc++.h>using namespace std;typedef unsigned long long ull;const int N = 25005;const int BASE = 129;int m, f[N], ans;string s[N];unordered_map<ull, int> um;ull h[N], p[N];
// l,r 1-basedull H(int l, int r) { if (l > r) return 0; return h[r] - h[l - 1] * p[r - l + 1];}
signed main() { cin >> m; p[0] = 1; for (int i = 1; i <= 20; i++) { p[i] = p[i - 1] * BASE; } for (int q = 1; q <= m; q++) { string s; cin >> s;
int len = s.size();
for (int i = 1; i <= len; i++) { h[i] = h[i - 1] * BASE + s[i - 1]; }
f[q] = 1;
// 增加一个 for (int i = 0; i <= len; i++) { for (char c = 'a'; c <= 'z'; c++) { ull hs = H(1, i) * p[len - i + 1] + c * p[len - i] + H(i + 1, len); if (um.count(hs)) f[q] = max(f[q], f[um[hs]] + 1); } } // 删除一个 for (int i = 1; i <= len; i++) { ull hs = H(1, i - 1) * p[len - i] + H(i + 1, len); if (um.count(hs)) f[q] = max(f[q], f[um[hs]] + 1); } // 修改一个 for (int i = 1; i <= len; i++) { for (char c = 'a'; c <= 'z'; c++) { ull hs = H(1, i - 1) * p[len - i + 1] + c * p[len - i] + H(i + 1, len); if (um.count(hs)) f[q] = max(f[q], f[um[hs]] + 1); } }
ans = max(ans, f[q]);
um[H(1, len)] = q; } cout << ans; return 0;}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!


