题目地址:

option=com_onlinejudge&Itemid=8&category=117&page=show_problem&problem=2832">UVA 11732 strcmp() Anyone?

题意: 

问strcmp函数的==语句运行了几次。

分析: 

大白上的题目。 

听说要用左儿子右兄弟的Trie。比較省空间。顺便学了下。

一边insert一边统计。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; #define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll; const int N = 0;
const int MAXNODE = 4000010; int n, cas;
ll ans;
char str[4001]; struct STrie {
int son[MAXNODE];
int bro[MAXNODE];
int val[MAXNODE];
char ch[MAXNODE];
int sz; STrie() { sz = 1; ch[0] = val[0] = bro[0] = son[0] = 0; }
void init() { sz = 1; ch[0] = val[0] = bro[0] = son[0] = 0; }
// inline int idx(char c) { return c - 'a'; } void insert(char *s) {
int len = strlen(s), u = 0, p;
repf (i, 0, len) {
// check the brother of u
for (p = son[u]; p; p = bro[p]) {
if (ch[p] == s[i])
break;
}
// cannot find out than insert
if (!p) {
p = sz++;
ch[p] = s[i];
bro[p] = son[u];
son[p] = 0;
val[p] = 0;
son[u] = p;
}
ans += (val[u] - val[p]) * (2 * i + 1);
if (len == i) {
ans += val[p] * (2 * i + 2);
val[p]++;
}
val[u]++;
u = p;
}
}
} trie; int main() {
// ios_base::sync_with_stdio(0);
while (~scanf("%d", &n) && n) {
trie.init();
ans = 0;
repf (i, 0, n - 1) {
scanf("%s", str);
trie.insert(str);
}
printf("Case %d: %lld\n", ++cas, ans);
}
return 0;
}
// UVa11732 strcmp() Anyone?
// Rujia Liu
#include<cstring>
#include<vector>
using namespace std; const int maxnode = 4000 * 1000 + 10;
const int sigma_size = 26; // 字母表为全体小写字母的Trie
struct Trie {
int head[maxnode]; // head[i]为第i个结点的左儿子编号
int next[maxnode]; // next[i]为第i个结点的右兄弟编号
char ch[maxnode]; // ch[i]为第i个结点上的字符
int tot[maxnode]; // tot[i]为第i个结点为根的子树包括的叶结点总数
int sz; // 结点总数
long long ans; // 答案
void clear() { sz = 1; tot[0] = head[0] = next[0] = 0; } // 初始时仅仅有一个根结点 // 插入字符串s(包括最后的'\0')。沿途更新tot
void insert(const char *s) {
int u = 0, v, n = strlen(s);
tot[0]++;
for(int i = 0; i <= n; i++) {
// 找字符a[i]
bool found = false;
for(v = head[u]; v != 0; v = next[v])
if(ch[v] == s[i]) { // 找到了
found = true;
break;
}
if(!found) {
v = sz++; // 新建结点
tot[v] = 0;
ch[v] = s[i];
next[v] = head[u];
head[u] = v; // 插入到链表的首部
head[v] = 0;
}
u = v;
tot[u]++;
}
} // 统计LCP=u的全部单词两两的比較次数之和
void dfs(int depth, int u) {
if(head[u] == 0) // 叶结点
ans += tot[u] * (tot[u] - 1) * depth;
else {
int sum = 0;
for(int v = head[u]; v != 0; v = next[v])
sum += tot[v] * (tot[u] - tot[v]); // 子树v中选一个串,其它子树中再选一个
ans += sum / 2 * (2 * depth + 1); // 除以2是每种选法统计了两次
for(int v = head[u]; v != 0; v = next[v])
dfs(depth+1, v);
}
} // 统计
long long count() {
ans = 0;
dfs(0, 0);
return ans;
}
}; #include<cstdio>
const int maxl = 1000 + 10; // 每一个单词最大长度 int n;
char word[maxl];
Trie trie; int main() {
int kase = 1;
while(scanf("%d", &n) == 1 && n) {
trie.clear();
for(int i = 0; i < n; i++) {
scanf("%s", word);
trie.insert(word);
}
printf("Case %d: %lld\n", kase++, trie.count());
}
return 0;
}

左儿子右兄弟Trie UVA 11732 strcmp() Anyone?的更多相关文章

  1. UVA11732 "strcmp()" Anyone?【左儿子右兄弟Trie】

    LINK1 LINK2 题目大意 给你一些字符串,并定义了一个函数(具体见题面) 问你把任意两个字符串放到函数里面得到的值的和是多少 思路 该怎么统计答案呢? 每次考虑当前插入的串和所有已经插入过的串 ...

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

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

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

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

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

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

  5. Uva 11732 strcmp() Anyone?

    strcmp() Anyone? Time Limit: 2000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Subm ...

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

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

  7. Vijos p1518 河流 转二叉树左儿子又兄弟

    左儿子又兄弟的转发一定要掌握啊,竞赛必用,主要是降低编程复杂度,省时间.个人觉得状压DP也是为了降低编程复杂度. 方程就不说了,程序应该能看得懂,用的记忆化搜索,方便理解. #include<c ...

  8. UVa 11732 strcmp()函数(左孩子右兄弟表示法)

    #include<iostream> #include<algorithm> #include<string> #include<cstring> #i ...

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

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

随机推荐

  1. css3实现连续不断的波浪

    给的波浪要比容器大,然后在左边准备一个相同的,注意,波浪头尾要能衔接起来,接着运动的长度为波浪的宽度,然后不断重复就好了

  2. 14深入理解C指针之---指针与内存分配

    一.内存的含义 1.定义:物理内存是固定,逻辑内存是非常灵活的 2.特征: 1).逻辑内存最终必须映射到物理内存才能作用 2).逻辑内存每次映射可能到不同的物理内存 3).逻辑内存与物理内存的链接通过 ...

  3. IOS 改变Navigation的返回按钮

    两个办法: 1, 手动为每一个UIViewController添加navigationItem的leftButton的设置代码 2,为UINavigationController实现delegate, ...

  4. dedecms--数据库

    最近在用dedecms做项目,dedecms里面有数据库操作类,其实这个在实际项目中用起来还是很方便的. 1:引入common.inc.php文件 require_once (dirname(__FI ...

  5. C#中流写入类StreamWriter的介绍

    C#中流写入类StreamWriter的介绍 (转) 应用FileStream类需要许多额外的数据类型转换工作,十分影响效率.使用StreamWriter类将提供更简单,更方便的操作方式.   Str ...

  6. LeetCode OJ——Two Sum

    http://oj.leetcode.com/problems/two-sum/ 求是否存在两个数的和为target,暴力法,两层循环 #include <iostream> #inclu ...

  7. Android 你应该注意的开发规范

    本文由Blankj投稿. Blankjd的博客地址: http://www.jianshu.com/u/46702d5c6978 为了利于项目维护以及规范开发,促进成员之间Code Review的效率 ...

  8. Linux进程管理(3):总结

    7. exit与_exit的差异    为了理解这两个系统调用的差异,先来讨论文件内存缓存区的问题. 在linux中,标准输入输出(I/O)函数都是作为文件来处理.对应于打开的每个文件,在内存中都有对 ...

  9. PHP 实现Word,excel等转换pdf

    近期做一个项目,须要将用户上传的word,excel文档转成PDF文档保存并打印.在网上找了非常多资料.并不全面,所以自己写了一份比較全面的教程来分享. 以下是操作步骤: 1.        安装免费 ...

  10. ListView中button监听器 设置 及 优化

    在应用开发中常常会用到ListView,而且每个Item里面都会有button之类的须要进行事件监听的控件.在给button加入OnClickListener的时候,一開始非常下意识的会想在ListV ...