[IOI2008]Type Printer打印機——[trie]

在這裏插入圖片描述
在這裏插入圖片描述
【題意分析】

要求操作數目最少,那麼可想而知最長的單詞就不用刪除了,打印一下就好了

然後我們可以根據輸入建出trie樹,首先最長的那個字符串每個字母都要在trie上打好標記。

然後進行DFS遍歷,如果在一個單詞的末尾就打印,然後記錄一下除了最長的字符串之外還有沒有字母可以輸出,否則就輸出一個減號(刪除標記)

遍歷到最長的一個字符串末尾時停止即可

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 500005
using namespace std;

char lgst[30], ans[MAXN << 1];
bool tag[MAXN], end[MAXN], flag = 0;
int tree[MAXN][27], n, maxlen = -1, sz, cnt;

namespace trie {

	inline void insert (char *s) {
		int now = 0;
		for (register int i = 1; i <= strlen (s + 1); i++) {
			int v = s[i] - 'a';
			if (! tree[now][v]) tree[now][v] = ++sz;
			now = tree[now][v];
		}
		end[now] = 1;
	}
	
	inline void settag (char *s) {
		int now = 0;
		for (register int i = 1; i <= strlen (s + 1); i++) {
			int v = s[i] - 'a';
			now = tree[now][v], tag[now] = 1;
		}
	}
	
	void DFS (int now) {
		if (end[now]) ans[++cnt] = 'P'; int opt = -1;
		for (register int i = 0; i < 26; i++)
			if (tag[tree[now][i]]) opt = i;
			else if (tree[now][i]) ans[++cnt] = i + 'a', DFS (tree[now][i]);
		if (opt != -1) ans[++cnt] = opt + 'a', DFS (tree[now][opt]);
		if (tag[now] && opt == -1) flag = 1;
		if (! flag) ans[++cnt] = '-';
	}

}using namespace trie;

int main () {
	scanf ("%d", &n);
	for (register int i = 1; i <= n; i++) {
		char s[30]; scanf ("%s", s + 1);
		int len = strlen (s + 1); insert (s);
		if (len > maxlen) maxlen = len, memcpy (lgst, s, sizeof s);
	}
	settag (lgst), DFS (0), printf ("%d\n", cnt);
	for (register int i = 1; i <= cnt; i++) putchar (ans[i]), puts ("");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章