洛谷 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)

相关推荐
nlpming6 分钟前
OpenClaw 代码解析
算法
学习永无止境@10 分钟前
MATLAB中矩阵转置
算法·matlab·fpga开发·矩阵
七颗糖很甜10 分钟前
雨滴谱数据深度解析——从原始变量到科学产品的Python实现【下篇】
python·算法·pandas
nlpming11 分钟前
OpenClaw system prompt定义
算法
nlpming11 分钟前
OpenClaw安装配置及简介
算法
爱码小白11 分钟前
MySQL 常用数据类型的系统总结
数据库·python·算法
玛丽莲茼蒿19 分钟前
Leetcode hot100 【中等】括号生成
算法·leetcode·职场和发展
小欣加油21 分钟前
leetcode 128 最长连续序列
c++·算法·leetcode·职场和发展
汀、人工智能33 分钟前
[特殊字符] 第94课:删除无效的括号
数据结构·算法·数据库架构·图论·bfs·删除无效的括号
pwn蒸鱼40 分钟前
leetcode:92. 反转链表 II
算法·leetcode·链表