专栏文章
题解:P13108 [GCJ 2019 #1A] Alien Rhyme
P13108题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miorzbdw
- 此快照首次捕获于
- 2025/12/03 00:11 3 个月前
- 此快照最后确认于
- 2025/12/03 00:11 3 个月前
居然还没有题解,赶紧来一发。
其实和正常字典树没什么区别,只是这里要求后缀,所以我们把字符串倒过来加入字典树。
如何得出答案?
其实也不难。后续遍历整棵字典树,如果能匹配就答案 ,然后这个节点的父节点的计数数组要全部 ,也就是减去以这个节点为根节点的子树的答案。
至于为什么要后续遍历,样例的第 个小数据就给出答案了。
因为每个重音后缀只能匹配两个字符,而先序遍历可能会找到多个有相同的重音后缀的字符。虽然稍微处理一下也可以过,但是后序遍历更简单。
其实和正常字典树没什么区别,只是这里要求后缀,所以我们把字符串倒过来加入字典树。
如何得出答案?
其实也不难。后续遍历整棵字典树,如果能匹配就答案 ,然后这个节点的父节点的计数数组要全部 ,也就是减去以这个节点为根节点的子树的答案。
至于为什么要后续遍历,样例的第 个小数据就给出答案了。
因为每个重音后缀只能匹配两个字符,而先序遍历可能会找到多个有相同的重音后缀的字符。虽然稍微处理一下也可以过,但是后序遍历更简单。
code
CPP#include<iostream>
using namespace std;
int trie[5005][60] , len , cnt[5005] , n;
void insert(string s){
int p = 0;
for(int i=s.size()-1;i>=0;i--){
int x = s[i] - 'A';
if(trie[p][x]==0)trie[p][x] = ++len;
p = trie[p][x] , cnt[p]++;
}
}
int solve(int i){
int res = 0;
int tmp = 0;
for(int c=0;c<26;c++){
if(trie[i][c]){
res += solve(trie[i][c]);
tmp += cnt[trie[i][c]] - res;
}
}
if(i!=0&&cnt[i]-res>=2)res += 2;
return res;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int T;cin >> T;
for(int x=1;x<=T;x++){
for(int i=0;i<=len;i++)for(int j=0;j<26;j++)trie[i][j] = 0 , cnt[i] = 0;
len = 0;
cin >> n;
for(int i=1;i<=n;i++){
string s;cin >> s;
insert(s);
}
cout << "Case #" << x << ": " << solve(0) << "\n";
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...