【題意分析】
要求操作數目最少,那麼可想而知最長的單詞就不用刪除了,打印一下就好了
然後我們可以根據輸入建出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;
}