首页 > 代码库 > UVa - 11732 - strcmp() Anyone?
UVa - 11732 - strcmp() Anyone?
先上题目:
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) |
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 }