洛谷 P4683 [IOI2008] Type Printer

原题点这里

题目来源于:洛谷

题目本质:深搜,字典树Trie

当时想法:当时看了题目标签,就有思路了(见代码注释),但一直RE+WA最后只剩下RE。

正确思路:

我们使用字典树来完成。

首先,有一个点大大的降低了题目难度,就是打印结束时,允许有部分字母留在打印机内

众所周知,字典树很好地利用了字符串的公共前缀,这也就是上一行出现的原因。

如果我们想要操作数尽可能少,那我们的删除数的操作就要尽可能的少。

插入函数:

cpp 复制代码
void insert(string s) {	//用我好同桌的筷子
	int p = 0;
	for (int i = 0; s[i]; i++) {
		int x = s[i] - 'a';
		if (!tree[p][x])
			tree[p][x] = ++ind; // 建点
		le[tree[p][x]] = x + 'a'; // 记录
		p = tree[p][x];
	}
	en[p] = 1; //标记结尾
}

标记最长:

cpp 复制代码
void mark(string s) {
	int p = 0;
	for (int i = 0; s[i]; i++) {
		int x = s[i] - 'a';
		k[tree[p][x]] = 1;
		p = tree[p][x];
	}
}

dfs:

cpp 复制代码
void dfs(int x) {
	if (en[x] == 1 && x != 0) {
		ans++;
		output += "P";
	}

	if (ans == n) {
		cout << output.size() << endl;
		for (int i = 0; output[i]; i++)
			cout << output[i] << endl;
		return;
	}

	int reg;
	for (int i = 0; i < 26; i++) {
		reg = tree[x][i];
		if (k[reg] == 0 && reg != 0) {
			output += le[reg];
			dfs(reg);
			output += "-";
		}
	}

	for (int i = 0; i < 26; i++) {
		reg = tree[x][i];
		if (k[reg] && reg) {
			output += le[reg];
			dfs(reg);
			output += "-";
		}
	}
}

主函数:

cpp 复制代码
int main() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		string s;
		cin >> s;
		shu(s);
		if (s.size() > p.size()){	//一样要判断字符串长度
			p = s;
		}
	}
	mark(p);
	dfs(0);	//	将输出掺杂到dfs里
	return 0;
}

我写的纯RE代码(思路可供参考)(洛谷高达64大分):

cpp 复制代码
//第二版不负众望又RE+WA了
//最后一次!
//What can I say!
//依旧感觉会崩掉
//纯RE没有WA了,CAO!
//前两版就不发了,大错特错!
#include<bits/stdc++.h>
using namespace std;
const int N = 25005;
const int M = 30;
int n, cur = 0, step = 1;
int tr[N][M];
char d[N];
bool mo[N], fla[N];
bool flag = false;
string q, p;
void shu(string s) {
	int fu = 0;
	int len = s.size();
	for (int i = 0; i < len; ++i) {
		int t = s[i] - 'a';
		if (tr[fu][t] == 0){
			tr[fu][t] = ++cur;
		}
		d[tr[fu][t]] = char(t + 'a');
		fu = tr[fu][t];
	}
	mo[fu] = true;
}
void mark(string s) {
	int fu = 0;
	int len=s.size();
	for (int i = 0; i < len; ++i) {
		int t = s[i] - 'a';
		fla[tr[fu][t]] = true;
		fu = tr[fu][t];
	}
}
void dfs(int mao) {
	if (mo[mao]) {
		++step;
		q = q + 'P';
	}
	if (step > n) {
		cout << q.size() << endl;
		int len=q.size();
		for (int i = 0; i < len; ++i){
			cout << q[i] << endl;
		}
		exit(0);	//直接退出
	}
	int x;
	int tmp = -1;	//使用tmp做临时标记
	for (int i = 0; i < 26; ++i) {
		x = tr[mao][i];
		if (fla[x]){
			tmp=x;
		}
		if (x != 0 && !fla[x]) {
			q = q + d[x];
			dfs(x);
		}
	}
	if (tmp != -1) {
		q = q + d[tmp];
		dfs(tmp);
	}
	if (tmp == -1 && fla[mao]){
		flag=true;
	}
	if (!flag){
		q = q + '-';
	}
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		string s;
		cin >> s;
		shu(s);
		if (s.size() > p.size()){	//一样要判断字符串长度
			p = s;
		}
	}
	mark(p);
	dfs(0);	//	将输出掺杂到dfs里
	return 0;
}

正解参考于:P4683 详解 - 洛谷专栏 (luogu.com.cn)

相关推荐
0 0 03 分钟前
CCF-CSP 37-2 机器人饲养指南(apple)【C++】考点:完全背包问题
开发语言·c++·算法
xiaoye-duck5 分钟前
《算法题讲解指南:优选算法-分治-归并》--49.计算右侧小于当前元素的个数,50.翻转对
c++·算法
_Twink1e5 分钟前
[算法竞赛]八、排序、排列
数据结构·c++·笔记·算法·排序算法
im_AMBER6 分钟前
Leetcode 137 组合 | 电话号码的字母组合
开发语言·算法·leetcode·深度优先·剪枝
Alex艾力的IT数字空间7 分钟前
OCR 原理:从像素到文本的智能转换
数据结构·人工智能·python·神经网络·算法·cnn·ocr
仟濹12 分钟前
【算法打卡day19(2026-03-11 周三)算法:打家劫舍-DP,双指针,二分查找,滑动窗口,方向控制,前缀和 】8个题
算法·leetcode·二分查找·动态规划
未来之窗软件服务12 分钟前
自己写算法(十)js加密UUID保护解密——东方仙盟化神期
java·javascript·算法·代码加密·东方仙盟算法
样例过了就是过了13 分钟前
LeetCode热题100 腐烂的橘子
数据结构·c++·算法·leetcode·bfs
Chan1621 分钟前
LeetCode 热题 100 | 链表
java·数据结构·spring boot·算法·leetcode·链表·java-ee
程序员小明儿22 分钟前
量子计算探秘:从零开始的量子编程与算法之旅 · 第五篇
算法·量子计算