UVA11732 左儿子右兄弟 Trie
2016-10-05 20:30
309 查看
tot[i]记录每个以i为根的树的叶子节点的数目
注意插入的时候要插入‘\0’ 为了分辨 前缀和相同的串
对于叶子节点 ans+=tot[u]*(tot[u]-1)/2*2*depth;
即相同的串两两一对的对数 *(2*深度)
对于非叶子节点 统计以其为根节点的串 两两一对的对数
for(int v=head[u];v;v=next[v]){
sum+=tot[v]*(tot[u]-tot[v]);//该节点和其他兄弟节点的叶子节点数(串数)
}
ans+=sum/2*(2*depth+1);///重复计算 除2
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=4010*1000+10;
typedef long long ll;
struct Trie
{
int head[maxn];
int next[maxn];
int tot[maxn];
char ch[maxn];
int sz;
ll ans;
void clear() {
head[0]=next[0]=tot[0]=0;
ans=0;
sz=1;
}
void insert(char *s) {
int l=strlen(s),v,u=0;
tot[0]++;
for(int i = 0; i <= l; ++i) {
bool found=0;
for(v=head[u];v!=0;v=next[v]) {
if(ch[v]==s[i]) {
found=1;
break;
}
}
if(!found) {
v=sz++;
ch[v]=s[i];
next[v]=head[u];
head[u]=v;
head[v]=0;
tot[v]=0;
}
u=v;
tot[u]++;
}
}
void dfs(int depth,int u) {
if(head[u]==0) {
ans+=tot[u]*(tot[u]-1)/2*2*depth;
}
else {
ll sum=0;
for(int v=head[u];v;v=next[v]){
sum+=tot[v]*(tot[u]-tot[v]);
}
ans+=sum/2*(2*depth+1);
for(int v=head[u];v;v=next[v]) {
dfs(depth+1,v);
}
}
}
ll count()
{
dfs(0,0);
return ans;
}
};
Trie trie;
int n;
char c[4010];
int main()
{
int Kase=0;
while(~scanf("%d",&n)&&n) {
trie.clear();
for(int i = 0; i < n; ++i) {
scanf("%s",c);
trie.insert(c);
}
printf("Case %d: %lld\n",++Kase,trie.count());
}
return 0;
}
注意插入的时候要插入‘\0’ 为了分辨 前缀和相同的串
对于叶子节点 ans+=tot[u]*(tot[u]-1)/2*2*depth;
即相同的串两两一对的对数 *(2*深度)
对于非叶子节点 统计以其为根节点的串 两两一对的对数
for(int v=head[u];v;v=next[v]){
sum+=tot[v]*(tot[u]-tot[v]);//该节点和其他兄弟节点的叶子节点数(串数)
}
ans+=sum/2*(2*depth+1);///重复计算 除2
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=4010*1000+10;
typedef long long ll;
struct Trie
{
int head[maxn];
int next[maxn];
int tot[maxn];
char ch[maxn];
int sz;
ll ans;
void clear() {
head[0]=next[0]=tot[0]=0;
ans=0;
sz=1;
}
void insert(char *s) {
int l=strlen(s),v,u=0;
tot[0]++;
for(int i = 0; i <= l; ++i) {
bool found=0;
for(v=head[u];v!=0;v=next[v]) {
if(ch[v]==s[i]) {
found=1;
break;
}
}
if(!found) {
v=sz++;
ch[v]=s[i];
next[v]=head[u];
head[u]=v;
head[v]=0;
tot[v]=0;
}
u=v;
tot[u]++;
}
}
void dfs(int depth,int u) {
if(head[u]==0) {
ans+=tot[u]*(tot[u]-1)/2*2*depth;
}
else {
ll sum=0;
for(int v=head[u];v;v=next[v]){
sum+=tot[v]*(tot[u]-tot[v]);
}
ans+=sum/2*(2*depth+1);
for(int v=head[u];v;v=next[v]) {
dfs(depth+1,v);
}
}
}
ll count()
{
dfs(0,0);
return ans;
}
};
Trie trie;
int n;
char c[4010];
int main()
{
int Kase=0;
while(~scanf("%d",&n)&&n) {
trie.clear();
for(int i = 0; i < n; ++i) {
scanf("%s",c);
trie.insert(c);
}
printf("Case %d: %lld\n",++Kase,trie.count());
}
return 0;
}
相关文章推荐
- UVA11732(左兄弟右儿子的Trie/Trie)
- (uva 11732) "strcmp()" Anyone? (trie+左儿子右兄弟表示法)
- UVa 11732 "strcmp()" Anyone? (左儿子右兄弟前缀树Trie)
- UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie)
- Uva 11732 "strcmp()" Anyone? 左儿子右兄弟的trie
- UVA 11732("strcmp()" Anyone?-Trie与左兄弟右儿子)
- 左儿子右兄弟Trie UVA 11732 strcmp() Anyone?
- UVA 11732 strcmp() Anyone? Trie的左儿子右兄弟表示法
- UVA 11732-"strcmp()" Anyone?-trie(左儿子右兄弟表示法(省空间))
- uva 11732 "strcmp()" Anyone? (trie+左儿子右兄弟表示法)
- UVA - 11732 "strcmp()" Anyone?左兄弟右儿子trie
- trie树 和 树的存储--左儿子右兄弟 --- uva 11732
- UVA 11732 strcmp() Anyone 左兄弟右孩子Trie
- UVA - 11732 依旧是字典树板子,和左儿子右兄弟法字典树
- "strcmp()" Anyone? UVA - 11732 左孩子右兄弟Trie/计数
- UVa 11732 strcmp函数 trie树 左儿子右兄弟表示法
- UVA 11732 "strcmp()" Anyone(字典树+左儿子-右兄弟表示法)
- UVA 11732 —— 左儿子右兄弟表示法&&Tire
- UVA 11732 "strcmp()" Anyone? Trie树 + 树的左儿子右兄弟存储法
- UVA 11732 - strcmp() Anyone?(Trie)