zoukankan      html  css  js  c++  java
  • UVA11732 "strcmp()" Anyone?

    题目链接:https://vjudge.net/problem/UVA-11732

    知识点:  字典树、儿子兄弟表示法

    解题思路:

      首先,为每一个字符的末尾添加一个 '$',因为有一种特殊情况:如果两个字符串(假设长度为 len )完全相同,则比较次数是 (2 len + 2) ,因为两个字符串末尾的 '' 也是相同的。

      用字典树维护字符串集。当插入字符串 (S) 中的一个字符时,算出字典树已有的字符串中跟 (S) 直到上一个字符都是相同的字符串数 (last),以及插入这个字符后仍然跟 (S) 相同的字符串数 (news),则对答案的贡献即为 ((news imes 2 + last - news)).

    AC代码:

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 const int maxn = 4000004;
     6 
     7 char ch[maxn]; //保存结点字符
     8 int son[maxn], bro[maxn];    //son是链表头, bro[u]表示u的下一个兄弟结点
     9 int nds; //nds是下一个可以分配的结点
    10 int cnt[maxn];  //cnt[x]表示经过结点x的字符串数
    11 
    12 ll add(char *str) {
    13     int len = strlen(str);
    14     str[len] = '$', str[len + 1] = '';
    15     ll ret = 0;
    16     //***********************************************
    17     //儿子-兄弟表示法(其实就是结合了链表的字典树,目的是节省空间)
    18     int now = 0;
    19     int last = cnt[now];
    20     for (int i = 0; i <= len; i++) {
    21         int v;
    22         for (v = son[now]; v; v = bro[v]) {
    23             if (ch[v] == str[i])   break;
    24         }
    25         if (!v) {
    26             bro[nds] = son[now];
    27             ch[nds] = str[i];
    28             cnt[nds] = son[nds] = 0;
    29             v = son[now] = nds++;
    30         }
    31         now = v;
    32         //************************************************
    33         int news = cnt[now];
    34         ret += news * 2;
    35         ret += (last - news);
    36         last = cnt[now];
    37         cnt[now]++;
    38     }
    39     return ret;
    40 }
    41 char str[4005];
    42 int main() {
    43     //    freopen("in.txt","r",stdin);
    44     int N, kase = 1;
    45     while (scanf("%d", &N) == 1 && N) {
    46         nds = 1, cnt[0] = son[0] = bro[0] = 0; //初始化
    47         ll ans = 0;
    48         while (N--) {
    49             scanf("%s", str);
    50             ans += add(str);
    51             cnt[0]++;
    52         }
    53         printf("Case %d: %lld
    ", kase++, ans);
    54     }
    55     return 0;
    56 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    更新证书错误Code Sign error: Provisioning profile ‘XXXX'can't be found
    解决Xcode 5下使用SVN出现 The operation couldn’t be completed. (NSURLErrorDomain error -1012.) 问题
    Android模拟器启动不了解决办法
    在AndroidManifest.xml文件中设置Android程序的启动界面方法
    Windows2008+MyEclipse10+Android开发环境搭配
    ADT下载地址整理
    android:inputType常用取值
    VS2010中使用Jquery调用Wcf服务读取数据库记录
    Linux手动安装netcore3.0
    StdOS之运行指示灯
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/8553194.html
Copyright © 2011-2022 走看看