P7537 [COCI2016-2017#4] Rima (字典树+树形 dp)
字典树 + 树形 dp
刻画一下限制,其实就是可以在末尾添加、替换、删除一个字母。然后我们发现,一定是先删除再增加,呈单谷状,两边的处理相似,只考虑一边的计算。将字符串翻转后放到字典树上考虑,其实就是树形 dp 求该节点子树内能够接多少个字符串,设
考虑答案,枚举最短的字符串的结束位置,那么就从儿子中选两个最大的
复杂度
#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back
using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 5e5 + 10;
int n, tot, ans = 1;
int tr[28 * N][28], ed[28 * N], f[28 * N];
void insert(std::string s) {
int u = 0;
for(int i = s.length() - 1; i >= 0; i--) {
int c = s[i] - 'a';
if(!tr[u][c]) tr[u][c] = ++tot;
u = tr[u][c];
}
ed[u]++;
}
void dfs(int u) {
int cnt = 0;
for(int i = 0; i < 26; i++) {
if(tr[u][i]) {
dfs(tr[u][i]);
if(ed[tr[u][i]]) f[u] = std::max(f[u], f[tr[u][i]]);
cnt += ed[tr[u][i]];
}
}
f[u] += std::max(0, cnt - 1) + ed[u];
}
void dfs2(int u) {
int max = 28 * N - 1, max2 = 28 * N - 1, cnt = 0;
for(int i = 0; i < 26; i++) {
if(tr[u][i]) {
if(f[max] < f[tr[u][i]] && ed[tr[u][i]]) max = tr[u][i];
cnt += ed[tr[u][i]];
}
}
for(int i = 0; i < 26; i++) {
if(tr[u][i]) if(f[max2] < f[tr[u][i]] && tr[u][i] != max && ed[tr[u][i]]) max2 = tr[u][i];
}
for(int i = 0; i < 26; i++) {
if(tr[u][i]) dfs2(tr[u][i]);
}
if(max != 28 * N - 1 && max2 != 28 * N - 1) ans = std::max(ans, f[max] + f[max2] + (cnt - 2) + ed[u]);
else if(max != 28 * N - 1) ans = std::max(ans, f[max] + (cnt - 1) + ed[u]);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n;
for(int i = 1; i <= n; i++) {
std::string s;
std::cin >> s;
insert(s);
}
dfs(0);
dfs2(0);
std::cout << ans << "\n";
return 0;
}
简洁版:
#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back
using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 5e5 + 10;
int n, tot, ans = 1;
int tr[29 * N][29], ed[29 * N], f[29 * N];
void insert(std::string s) {
int u = 0;
for(int i = s.length() - 1; i >= 0; i--) {
int c = s[i] - 'a';
if(!tr[u][c]) tr[u][c] = ++tot;
u = tr[u][c];
}
ed[u]++;
}
void dfs(int u) {
int max = 0, max2 = 0, cnt = 0;
for(int i = 0; i < 26; i++) {
if(tr[u][i]) {
int v = tr[u][i];
dfs(v);
if(max < f[v]) max2 = max, max = f[v];
else if(max2 < f[v]) max2 = f[v];
cnt += ed[v];
}
}
if(ed[u]) f[u] = max + std::max(cnt, 1);
ans = std::max(ans, max + max2 + ed[u] + std::max(cnt - 2, 0));
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n;
for(int i = 1; i <= n; i++) {
std::string s;
std::cin >> s;
insert(s);
}
dfs(0);
std::cout << ans << "\n";
return 0;
}
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具