题目大意:
现有一种过滤器,可以屏蔽以该过滤器为前缀的网站
给出一些需要被屏蔽和不能被屏蔽的网站
无法满足条件输出$-1$
在满足条件的情况下,最小化过滤器的串长之和
按字典序输出所有过滤器
以所有不能被屏蔽网站的名字建立一棵$Trie$
考虑插入每个需要被屏蔽网站的名字的过程
- 若经过的所有节点均是不能被屏蔽的,则无解
- 否则,将开头到第一个未在$Trie$中出现的字符作为一个过滤器,标记该过滤器并退出插入过程
- 若发现当前名字以一个过滤器为前缀,则不需要新增过滤器,可直接退出插入过程
该贪心的正确性显然1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using namespace std;
const int N=2e5+50,rt=0;
int n,cnt=0,ch[N][26],col[N],idx=0;
char str[N];
string s[N];
vector<string> ans;
inline char get()
{
register char ch=getchar();
while (ch!='+'&&ch!='-') ch=getchar();
return ch;
}
void insert(string s)
{
int o=rt;
for(int i=0;i<s.size();i++)
{
if (!ch[o][s[i]-'a'])
ch[o][s[i]-'a']=++cnt;
o=ch[o][s[i]-'a'];
col[o]=1;
}
}
void find(string s)
{
int o=rt;
string w="";
for(int i=0;i<s.size();i++)
{
if (!ch[o][s[i]-'a'])
{
w.append(1,s[i]);
ch[o][s[i]-'a']=++cnt;
ans.push_back(w);
return;
}
w.append(1,s[i]);
o=ch[o][s[i]-'a'];
if (!col[o]) return;
}
puts("-1"),exit(0);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char opt=get();
scanf("%s",str);
if (opt=='+')
insert(str);
else s[++idx]=str;
}
for(int i=1;i<=idx;i++) find(s[i]);
sort(ans.begin(),ans.end());
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
printf("%s\n",ans[i].c_str());
return 0;
}