UVa - 11732 - strcmp() Anyone?

先上题目:

strcmp() Anyone?

Time Limit:2000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

Submit Status

Description


J


?strcmp()? Anyone?

Input: Standard Input

Output: Standard Output

strcmp() is a library function in C/C++ which compares two strings. It takes two strings as input parameter and decides which one is lexicographically larger or smaller: If the first string is greater then it returns a positive value, if the second string is greater it returns a negative value and if two strings are equal it returns a zero. The code that is used to compare two strings in C/C++ library is shown below:


int strcmp(char *s, char *t)
{
    int i;
    for (i=0; s[i]==t[i]; i++)
        if (s[i]==‘\0‘)
            return 0;
    return s[i] - t[i];
}


Figure: The standard strcmp() code provided for this problem.

The number of comparisons required to compare two strings in strcmp() function is never returned by the function. But for this problem you will have to do just that at a larger scale. strcmp() function continues to compare characters in the same position of the two strings until two different characters are found or both strings come to an end. Of course it assumes that last character of a string is a null (?\0?) character. For example the table below shows what happens when ?than? and ?that?; ?therE? and ?the? are compared using strcmp() function. To understand how 7 comparisons are needed in both cases please consult the code block given above.


t


h


a


N


\0


 


t


h


e


r


E


\0


 


=


=


=



 


=


=


=



 


 


t


h


a


T


\0


t


h


e


\0


 


 


Returns negative value

7 Comparisons


Returns positive value

7 Comparisons

Input

The input file contains maximum 10 sets of inputs. The description of each set is given below:

Each set starts with an integer N (0<N<4001) which denotes the total number of strings. Each of the next N lines contains one string. Strings contain only alphanumerals (?0?? ?9?, ?A?? ?Z?, ?a?? ?z?) have a maximum length of 1000, and a minimum length of 1.

Input is terminated by a line containing a single zero. Input file size is around 23 MB.

Output

For each set of input produce one line of output. This line contains the serial of output followed by an integer T. This T denotes the total number of comparisons that are required in the strcmp() function if all the strings are compared with one another exactly once. So for N strings the function strcmp() will be called exactly  times. You have to calculate total number of comparisons inside the strcmp() function in those  calls. You can assume that the value of T will fit safely in a 64-bit signed integer. Please note that the most straightforward solution (Worst Case Complexity O(N2 *1000)) will time out for this problem.

Sample Input                              Output for Sample Input


2

a

b

4

cat

hat

mat

sir

0


Case 1: 1

Case 2: 6


Problem Setter: Shahriar Manzoor, Special Thanks: Md. Arifuzzaman Arif, Sohel Hafiz, Manzurur Rahman Khan

  题意:给你n个长度不超过1000的字符串,问你根据它给出的公式需要比较多少次。

  显然暴力匹配是不行的,这里的做法是建一棵Trie树来保存字符串,然后在每次插入字符串的时候就统计当前需要判断多少次。经过分析,我们可以发现对于有相同前缀的两个字符串,需要比较的次数等于前缀长度*2+从前缀以后不开匹配的那一位的一次比较。也就是说如果两个串A、B,A=abcaa,B=abcbb的话那就需要一共比较7次。如果两个字符串的完全相同的话,我们需要比较的次数就是一个字符串的长度*2。这里所说的长度是算上终止符‘\0‘,因为这个位置也需要判断。

  那么究竟需要怎样统计才能得到正确的结果呢。我们可以发现如果当前已经插入了一个字符串,那么当我再插入一个新的字符串的字符串的时候,对于相同位置的相同位,我们都需要比较两次,而对于相同位置的不相同的字符,我们只会比较一次,同时,我们发现,对于所有的字符串,两两之间至少也要比较一次。那么我们可以这样设计代码:在访问到相同位置有相同的字符的时候,我们就每有一对相同的字符就加2,对于不相同的字符,那么我们知道那只会比较一次以后就结束了比较(对于这两个字符串来说),我们可以在最后再加这些次数,因为对于整体来说,这些次数是不会变的。而当我们比较两个相同的字符串的时候,当我们比较到终止符的时候,我们只加一,这样我们就可以将剩下的那个一相加放在总体处理上面了。(如果不懂的话可以根据代码手动模拟一次就可能懂了)。

  有了思路,然后就是代码的实现了,一开始我用的方法是开一个4000*1000*62的二维数组,来实现Trie树,但是超时了,我想主要的原因在于每一次开新的节点的时候都需要初始化的缘故,同时这种方法并不能很好地利用空间。然后在网上看了一下别人的方法是将第二维的长度62的数组也做成邻接表,这样就可以省去多次初始化,这种方法好像是叫左兄弟右孩子的构图,值得学习一下。详细实现过程看代码。

上代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #define MAXN 4001010
 4 #define ll long long
 5 using namespace std;
 6
 7 int head[MAXN];
 8 int next[MAXN];
 9 int tot[MAXN];
10 int ed[MAXN];
11 char ch[MAXN];
12 int sz;
13 ll sum;
14 void init(){
15      sz=1; head[0]=next[0]=tot[0]=0; sum=0;
16 }
17
18 void insert(char *s){
19      int u,v,n=strlen(s);
20      u=0;
21      for(int i=0;i<n;i++){
22         bool f=0;
23         for(v=head[u];v!=0;v=next[v]){
24             if(ch[v]==s[i]){
25                 f=1; break;
26             }
27         }
28         if(!f){
29             v=sz++;
30             tot[v]=0;
31             ed[v]=0;
32             ch[v]=s[i];
33             next[v]=head[u];
34             head[u]=v;
35             head[v]=0;
36         }
37         u=v;
38         sum+=tot[v]*2;
39         tot[v]++;
40      }
41      sum+=ed[u];
42      ed[u]++;
43 }
44
45
46 int main()
47 {
48     int n;
49     char s[1002];
50     //freopen("data.txt","r",stdin);
51     for(int z=1;scanf("%d",&n),n;z++){
52         init();
53         for(int i=0;i<n;i++){
54             scanf("%s",s);
55             insert(s);
56         }
57         printf("Case %d: %lld\n",z,sum+n*(n-1)/2);
58     }
59     return 0;
60 }

/*11732*/

UVa - 11732 - strcmp() Anyone?,布布扣,bubuko.com

时间: 2024-10-19 15:56:39

UVa - 11732 - strcmp() Anyone?的相关文章

uva 11732 - strcmp() Anyone?(字典树)

题目链接:uva 11732 - strcmp() Anyone? 题目大意:给定n个串,然后两两之间比较,问说总共要比较多少次. 解题思路:字典树,建立出字典树,然后根据字典树的性质在节点记录有多少个字符串包含该节点.因为节点的个数比较多,所以用左孩子右兄弟的方法建立字典树. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long

左儿子右兄弟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? 题目链接 题意:给定一些字符串,要求两两比较,需要比较的总次数(注意,如果一个字符相同,实际上要还要和'\0'比一次,相当比2次) 思路:建Trie树,每次建树过程中,后继后继结点就是相同结点需要比较两次ans + val * 2,否则就是不同结点ans + val,建完树就计算完了 代码: #include <cstdio> #include <cstring> const int N = 1005; const int

uva 11732 - strcmp() Anyone? 不错的Trie题

题解:http://blog.csdn.net/u013480600/article/details/23122503 我的代码一直TLE,,,看了人家的之后,觉得1.链式前向星比较好,2.*depth而不是每过一个节点就计算,这一点很好 我是基本copy别人的代码,自己加了注释,留个记号,随后重写, 这道题同样作为链式前向星的Trie的模板 #include <cstdio> #include <cstring> #include <iostream> using n

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的, 我们必须对其进行优化,看了

UVA 11732 &quot;strcmp()&quot; Anyone? (Trie)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 题意:模拟strcmp()函数,给n个字符串,两两之间进行比较,问需要进行多少次比较? 解析:字符串很多,数据量大,按题意两两比较显然不现实.如果把所有的单词插入到一棵Trie里面会怎么样呢?考虑than和that对应的结点,than和that的前3个字符是一样的,但第4个

UVA 11732 strcmp() Anyone? (压缩版字典树)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 按照正常的字典树建树会MLE 所以需要采用树的压缩算法来建树 #include <cstdio> #include <iostream> #include <cstring> #define maxn 4000010 #define ma

UVA 11732(&quot;strcmp()&quot; Anyone?-Trie与左兄弟右儿子)

"strcmp()" Anyone? strcmp() is a library function in C/C++ which compares two strings. It takes two strings as input parameter and decides which one is lexicographically larger or smaller: If the first string is greater then it returns a positiv