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

LINK1

LINK2


题目大意

给你一些字符串,并定义了一个函数(具体见题面)

问你把任意两个字符串放到函数里面得到的值的和是多少

思路

该怎么统计答案呢?

每次考虑当前插入的串和所有已经插入过的串一起统计答案

然后考虑一下怎么统计,假设当前深度是dep

并且现在是u,即将向v移动指针

那么怎么同几当前这一层的答案呢?

所有在v的子树中的节点显然是不能在这一层统计答案的

所以就考虑统计和所有不在同一个子树的答案

具体实现很简单,读者自己思考吧



注意在每一次走到字符串的末尾的时候需要特判

和他相同或者包含它的字符串会比较更多的次数,所以不能直接停止也要继续移动指针,可以强行让最后一个位置变成奇怪字符

然后这题需要左兄弟右儿子的trie

具体实现参考代码(其实并不麻烦,别怕)


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
typedef pair<int, int> pi;
typedef long long ll;
typedef double db;
#define fi first
#define se second
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
void Read(T &x) {
  bool w = 1;x = 0;
  char c = getchar();
  while (!isdigit(c) && c != '-') c = getchar();
  if (c == '-') w = 0, c = getchar();
  while (isdigit(c)) {
    x = (x<<1) + (x<<3) + c -'0';
    c = getchar();
  }
  if (!w) x = -x;
}
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 6e6 + 10;
struct Node {
  char ch;
  int val;
  Node *son, *bro;
  Node(char ch = 0, int val = 0, Node *son = NULL, Node *bro = NULL):ch(ch), val(val), son(son), bro(bro) {}
} *rt, pool[N], *cur = pool;
ll ans;
void insert(char *s) {
  int len = strlen(s);
  s[len] = '#';
  Node *u = rt, *v;
  fu(i, 0, len) {
    v = u->son;
    for (; v; v = v->bro)
      if (v->ch == s[i]) break;
    if (!v) {
      v = new (cur++) Node(s[i], 0, NULL, u->son);
      u->son = v;
    }
    ans += 1ll * (u->val - v->val) * (2 * i + 1);
    if (i == len) {
      ans += 1ll * v->val * (2 * len + 2);
      ++v->val;
    }
    ++u->val;
    u = v;
  }
}
char s[N];
int main() {
#ifdef dream_maker
  freopen("input.txt", "r", stdin);
#endif
  int n, tot = 0;
  while (1) {
    Read(n);
    if (!n) break;
    cur = pool;
    rt = new (cur++) Node();
    ans = 0;
    fu(i, 1, n) {
      scanf("%s", s);
      insert(s);
    }
    printf("Case %d: %lld\n", ++tot, ans);
  }
  return 0;
}

原文地址:https://www.cnblogs.com/dream-maker-yk/p/9904701.html

时间: 2024-12-15 04:10:30

UVA11732 "strcmp()" Anyone?【左儿子右兄弟Trie】的相关文章

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

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 一边inser

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

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 开始先建树记录次数,然后再遍历统计,结果错了... 后面参考了Shoutmon巨巨的写法,一边insert一边统计. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

UVa 11732 &quot;strcmp()&quot; Anyone? (左儿子右兄弟前缀树Trie)

题意:给定strcmp函数,输入n个字符串,让你用给定的strcmp函数判断字符比较了多少次. 析:题意不理解的可以阅读原题https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 字符串很多,又很长,如果按照题目的意思两两比较,肯定会TLE,所以要用前缀树(Trie)来解决,当然只是用简单的前缀树也会TLE的, 我们必须对其进行优化,看了

左儿子右兄弟表示法

顾名思义 每个节点一个为儿子指针,一个为兄弟指针(在加个父亲) 这样就避免了儿子个数不均带来的问题 TOJ TOJ4077 用一个指针记录当前在哪个节点,需要注意的是可以有多个重名的文件,但是不能在一个目录下. 所以用文件名和其父亲节点作为一个文件的id(区分其他). #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm

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

左儿子又兄弟的转发一定要掌握啊,竞赛必用,主要是降低编程复杂度,省时间.个人觉得状压DP也是为了降低编程复杂度. 方程就不说了,程序应该能看得懂,用的记忆化搜索,方便理解. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 bool p[103]; 6 int N,K,point[103],next[203],v[203],c[203],w[103]

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

1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 8 const int maxn = 4000 * 1000 + 10; 9 int n; 10 long long ans; 11 12 struct Trie 13 { 14 int head[

任意有根树的左孩子右兄弟表示法存储

算法导论:10.4-4 对一个含n个结点的任意有根树,写出一个O(n)时间的过程,输出其所有关键字. 该树以左孩子或兄弟表示法存储. #ifndef _ROOTED_TREE_H_ #define _ROOTED_TREE_H_ /***************************************************************** 算法导论:10.4-4 对一个含n个结点的任意有根树,写出一个O(n)时间的过程,输出其所有关键字. 该树以左孩子或兄弟表示法存储. *

uva11732 strcmp() Anyone?

题意:给出多个字符串,两两配对,求总配对次数. 思路:如果两个字符串一样,ans=strlen(字符串)*2+2,如果不同,ans=公共前缀长度*2+1:用左儿子右兄弟建字典树.插入一个字符计算一次. 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <iostream> 6 #include <algori

编程题:strcmp()函数的作用是:从左到右逐个字符比较。遇见‘\0’为止。

编程题:strcmp()函数的作用是:从左到右逐个字符比较.(按照字符对应的ascii码值比较)遇见'\0'为止. #include<stdio.h> #include<string.h> int string_compare(char string1[],char string2[]) { int i=0; while(string1[i]==string2[i]&&string1[i]!='\0') i++; return string1[i]-string2[