uva11732 - strcmp() Anyone? 前缀树

来源:互联网 发布:淘宝美工图片尺寸 编辑:程序博客网 时间:2024/05/05 16:00

strcmp() is a library function inC/C++ which compares two strings. It takes two strings as input parameter anddecides which one is lexicographically larger or smaller: If the first stringis greater then it returns a positive value, if the second string is greater itreturns a negative value and if two strings are equal it returns a zero. Thecode 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 comparisonsrequired to compare two strings in strcmp() function is never returned by thefunction. 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 thetwo strings until two different characters are found or both strings come to anend. 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 comparisonsare 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 10sets 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 Nlines 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 setof input produce one line of output. This line contains the serial of outputfollowed by an integer T. This T denotes the total number of comparisons thatare required in the strcmp() function if all the strings are compared with oneanother exactly once. So for N strings the function strcmp() will be called exactly times. You have tocalculate total number of comparisons inside the strcmp() function in those calls. You can assumethat the value of T will fit safely in a 64-bit signed integer. Please notethat the most straightforward solution (Worst Case Complexity O(N2*1000)) will time out for this problem.

 

Sample Input                              Output for SampleInput

2

a

b

4

cat

hat

mat

sir

0

Case 1: 1

Case 2: 6

 


   字符串比较,如果第一位和第二位相等就继续比较,如果不想等或都为0就停止比较,问两两互相比较要多少次。一开始用正常的字典树,数组开太大超时。于是学习了这个左儿子右兄弟法,用链表head[u]表示u的左儿子,next[u]表示u的右兄弟,也就是查找儿子的时候用链表查找省空间。

     在查询的过程中完成计算。用cnt[u]表示目前经过节点u的单词个数,val[u]表示目前在u节点截止的单词个数。每次经过u,就至少要比cnt[u]次,因为相等的话要比两次,所以找到下一个节点v的时候还要加上cnt[v]。也就是cnt[u]+cnt[v]就是要和v节点比较的次数。注意结束的时候要特判一下0的情况。

#include<iostream>#include<cstdio>#include<cstring>#define MAXN 1010#define MAXNODE 4000*1010#define INF 0x3f3f3f3fusing namespace std;int N;long long ans;char str[MAXN];struct Tire{    int head[MAXNODE],next[MAXNODE],cnt[MAXNODE],val[MAXNODE],sz;    char ch[MAXNODE];    void init(){        memset(head,0,sizeof(head));        memset(next,0,sizeof(next));        memset(cnt,0,sizeof(cnt));        memset(val,0,sizeof(val));        sz=1;    }    void insert(char *s){        int u=0,v;        for(int i=0;s[i];i++){            ans+=cnt[u];            cnt[u]++;            int flag=0;            for(v=head[u];v;v=next[v]) if(s[i]==ch[v]){                flag=1;                break;            }            if(!flag){                v=sz++;                next[v]=head[u];                head[u]=v;                ch[v]=s[i];            }            u=v;            ans+=cnt[u];        }        ans+=cnt[u]+val[u];        val[u]++;        cnt[u]++;    }}tire;int main(){    freopen("in.txt","r",stdin);    int cas=0;    while(scanf("%d",&N),N){        ans=0;        tire.init();        for(int i=0;i<N;i++){            scanf("%s",str);            tire.insert(str);        }        printf("Case %d: %lld\n",++cas,ans);    }    return 0;}



0 0
原创粉丝点击