题解:http://blog.csdn.net/u013480600/article/details/23122503

我的代码一直TLE,,,看了人家的之后,认为1、链式前向星比較好,2、*depth而不是每过一个节点就计算,这一点非常好

我是基本copy别人的代码,自己加了凝视,留个记号,随后重写,

这道题相同作为链式前向星的Trie的模板

#include <cstdio>
#include <cstring>
#include <iostream> using namespace std;
#define ll long long
const int MAXN=4002*1002+100; struct Trie
{
int head[MAXN];//其值为在边集的下标
int next[MAXN];//next[j]第j条边的下一条边在边集的下标
int tot[MAXN];
char str[MAXN];//相当于边集了 边存储字符
int sz;//head下标的上界,也相当于节点
ll ans;
void clear()
{
ans=0;
sz=1;
head[0]=next[0]=tot[0]=0; }
void insert(char *s)
{
int n=strlen(s),u=0;
tot[u]++;
for(int i=0;i<=n;i++)//空字符也插入
{
bool found=false;
for(int j=head[u];j;j=next[j])
if(str[j] == s[i])
{
u=j;
found=true;
break;
}
if(!found)//节点不存在
{
next[sz]=head[u];
head[u]=sz; head[sz]=0;//
tot[sz]=0;//新的节点还没有连边
str[sz]=s[i];//初始化边信息,边存储字符
u=sz++;//u存储新的子结点
}
tot[u]++;
}
}
void dfs(int dep, int u)
{
if(!head[u])//到了叶子节点
{
ans+=tot[u]*(tot[u]-1)*dep;
}
else
{
int sum=0;
for(int v=head[u];v;v=next[v]) //**
sum+=tot[v]*(tot[u]-tot[v]);//**
ans+= sum/2*(dep*2+1);//这里我自己做的时候没有想到,,,,事实上分叉后跟分叉前都能够用上面标注**的方法计算
for(int v=head[u];v;v=next[v])
dfs(dep+1,v);
}
}
ll cal()
{
ans=0;
dfs(0,0);
return ans;
}
};
Trie trie;
char word[1000+100];
int main()
{ int icase=0,n;
while(scanf("%d",&n) && n)
{
trie.clear();
for(int i=0;i<n;i++)
{
scanf("%s",word);
trie.insert(word);
}
printf("Case %d: %lld\n",++icase,trie.cal());
}
return 0;
}

我的tle的代码  随后改动

#include <cstdio>
#include <cstring>
#include <iostream> using namespace std; #define ll long long const int N = 4011*1000+10;
const int tk = 75;
const int tb = '0'; // tk叉; 起始字母为tb;
int top, tree[N][tk + 2]; // N: 最大结点个数 top: 第一层有多少节点
char str[1010];
void init(){
top = 1;
memset(tree[0], 0, sizeof(tree[0]));
} void Insert(char*s, int Rank = 1){
int rt, nxt;
for(rt = 0; *s; rt = nxt, ++s) {
nxt = tree[rt][*s - tb]; if(0 == nxt) {//没被使用时插入
tree[rt][*s - tb] = nxt = top;
memset(tree[top], 0, sizeof(tree[top]));
top++;
}
tree[nxt][tk]++;//其值表示有多少单词经过
}
tree[rt][tk+1] = Rank;//1表示存在0表示不存在,也能够赋予其其它含义
} ll solve(int rt,int last)
{
if(tree[rt][tk] <= 1)return 0;
//到结尾仅仅须要比較一次,假设仅仅有一个,也仅仅须要比較一次
ll ans=0;
for(int i=0;i<tk;i++)
if(tree[rt][i])
{
ans=ans+tree[tree[rt][i]][tk]*(last-tree[tree[rt][i]][tk]);//计算子树森林
} ans/=2;
for(int i=0;i<tk;i++)
{
if(tree[rt][i])
{
ans+=solve(tree[rt][i],tree[tree[rt][i]][tk]);
} }
//return ans+2*C[tree[rt][tk]][2];
return ans+tree[rt][tk]*(tree[rt][tk]-1);
}
int main()
{
freopen("uva11732.txt","r",stdin);
int icase=0,n,len;
//calC();
while(scanf("%d",&n)==1 && n)
{
init();
tree[0][tk]=n;
for(int i=0;i<n;i++)
{
scanf("%s",str);
Insert(str);
} printf("Case %d: %lld\n",++icase,solve(0,n)-n*(n-1));
}
return 0;
}

uva 11732 - strcmp() Anyone? 不错的Trie题的更多相关文章

  1. UVA 11732 - strcmp() Anyone?(Trie)

    UVA 11732 - strcmp() Anyone? 题目链接 题意:给定一些字符串,要求两两比較,须要比較的总次数(注意.假设一个字符同样.实际上要还要和'\0'比一次,相当比2次) 思路:建T ...

  2. 左儿子右兄弟Trie UVA 11732 strcmp() Anyone?

    题目地址: option=com_onlinejudge&Itemid=8&category=117&page=show_problem&problem=2832&qu ...

  3. UVa 11732 "strcmp()" Anyone? (左儿子右兄弟前缀树Trie)

    题意:给定strcmp函数,输入n个字符串,让你用给定的strcmp函数判断字符比较了多少次. 析:题意不理解的可以阅读原题https://uva.onlinejudge.org/index.php? ...

  4. UVA 11732 strcmp() Anyone?(Trie的性质)

    strcmp() Anyone? strcmp() is a library function in C/C++ which compares two strings. It takes two st ...

  5. UVA - 11732 "strcmp()" Anyone?左兄弟右儿子trie

    input n 2<=n<=4000 s1 s2 ... sn 1<=len(si)<=1000 output 输出用strcmp()两两比较si,sj(i!=j)要比较的次数 ...

  6. UVA - 11732 "strcmp()" Anyone? (trie)

    https://vjudge.net/problem/UVA-11732 题意 给定n个字符串,问用strcmp函数比较这些字符串共用多少次比较. strcmp函数的实现 int strcmp(cha ...

  7. Trie UVA 11732 "strcmp()" Anyone?

    题目传送门 题意:询问所有字符串的比较次数和(注意for循环内的比较也算) 分析:将所有字符串插入到字典树上,然后结点信息记录有几个字符串,那么每走到一个结点就能知道比较到此时需要的次数.学习到链表存 ...

  8. UVA 11732 strcmp() Anyone (Trie+链表)

    先两两比较,比较次数是两者相同的最长前缀长度*2+1,比较特殊的情况是两者完全相同时候比较次数是单词长度*2+2, 两个单词'末尾\0'和'\0'比较一次,s尾部'\0'和循环内'\0'比较一次. 因 ...

  9. UVA 11732 - strcmp() Anyone? 字典树

    传送门:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

随机推荐

  1. 基于visual Studio2013解决C语言竞赛题之0514单词统计

     题目 解决代码及点评 /************************************************************************/ /* 14. 有一行字 ...

  2. centos 推荐使用epel源

    centos 推荐使用epel源 张映 发表于 2011-10-13 分类目录: linux 在dell r410上面装的是centos6,64的操作系统,用的163的源,我一直都是用163的源,比较 ...

  3. 什么是TimeTunnel

    index - Taocode 欢迎使用TimeTunnel PageOutline(1-3,,inline) 什么是TimeTunnel !TimeTunnel(简称TT)是一个基于thrift通讯 ...

  4. coreldraw圆形裁剪

    裁剪方法: http://zhidao.baidu.com/link?url=9-OuTkkr7igOHgKDOhJgU6iUYY5MeGEGdNXX8p6RGq79Im4va0UdMAmH4gSDz ...

  5. SqlServer字段说明查询(表基本信息查询)

    --快速查看表结构(比较全面的) THEN obj.name ELSE '' END AS 表名, col.colorder AS 序号 , col.name AS 列名 , ISNULL(ep.[v ...

  6. JVM --需要知道的一些术语

    1. Java堆中各代分布: Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息, ...

  7. 14-UIKit(拖拽手势、布局)

    目录: 1.手势创建的拖拽方式 2.frame,bounds,transform,center区别 3.触控(touch) 4.布局 5.代码布局 回到顶部 1.手势创建的拖拽方式 创建手势对象,修改 ...

  8. C# 使用IENUMERABLE,YIELD

    C# 使用IENUMERABLE,YIELD 前言 在上篇文章中我得出结论,遍历迭代器修改迭代器中项目的值未生效,是因为使用了yield return,并且每次遍历迭代器都执行返回迭代器的方法.这篇文 ...

  9. 信号与槽(可以与第三方库混用,首次见到QObject::destroyed的使用)

    信号与槽用于对象之间的通信.信号与槽机制是Qt的核心特性和区别于其他框架的特性. Introduction 在GUI程序中,当我们改变一个widget,经常需要其他的widget得到通知.更普遍的是, ...

  10. C语言中 移位操作运算

    移位规律: 左移时总是移位和补零.右移时无符号数是移位和补零,此时称为逻辑右移;而有符号数大多数情况下是移位后补最左边的位(也就是补最高有效位),移几位就补几位,此时称为算术右移.(其实跟扩展逻辑一样 ...