P7537 [COCI2016-2017#4] Rima (字典树+树形 dp)

P7537 [COCI2016-2017#4] Rima

字典树 + 树形 dp

刻画一下限制,其实就是可以在末尾添加、替换、删除一个字母。然后我们发现,一定是先删除再增加,呈单谷状,两边的处理相似,只考虑一边的计算。将字符串翻转后放到字典树上考虑,其实就是树形 dp 求该节点子树内能够接多少个字符串,设 fu 表示 u 节点子树下能够接多少个串,转移易得。

考虑答案,枚举最短的字符串的结束位置,那么就从儿子中选两个最大的 fvfv2,把他们拼起来计算贡献。

复杂度 O(szi)

#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;
}
posted @   Fire_Raku  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示