hdu 1800 Flying to the Mars 字典树

来源:互联网 发布:校园网络广播系统 编辑:程序博客网 时间:2024/05/16 05:55

题目:给出n个数字0<=n<=3000每个数字位数小于30,较大的可以和较小的共用一把扫把(不一定只有两个数,也就是说可以多个数公用一个扫把),求最少用多少把扫把。

分析:只要给定的数都不相同,那么只需要一把扫把即可。这样,问题就转化成了找出给出的数里重复的次数,重复次数最多的数的个数即为所求。因为每个数字位数小于30位,若用排序的话效率较低,则采用字典树。将每个数当作字符串插入字典树,记录没个数出现的次数,最后查找就好了。注意,04与4都表示4,在插入时不将0插入。

我一开始错的原因是清零字典树时把a1(节电个数)赋值为0,这样是不行的,因为还有一个根节点。

程序:

var  ans,n,i,a1:longint;  son:array[1..90000,1..10] of longint;  s:array[1..90000] of char;  a:array[1..90000,1..2] of longint;  str:string;procedure insert(x:longint;str:string);var  i:longint;begin  if str='' then  begin    inc(a[x,2]);    exit;  end;  for i:=1 to a[x,1] do    if s[son[x,i]]=str[1] then    begin      delete(str,1,1);      insert(son[x,i],str);      exit;    end;  inc(a1);  inc(a[x,1]);  son[x,a[x,1]]:=a1;  a[a1,1]:=0;  a[a1,2]:=0;  s[a1]:=str[1];  delete(str,1,1);  insert(a1,str);end;procedure count(x:longint);var  i:longint;begin  if a[x,2]>ans then ans:=a[x,2];  for i:=1 to a[x,1] do    count(son[x,i]);end;begin  while not eof do  begin    readln(n);    a[1,1]:=0;    a[1,2]:=0;    a1:=1;    for i:=1 to n do    begin      readln(str);      while (str[1]='0')and(str<>'0') do delete(str,1,1);      insert(1,str);    end;    ans:=0;    count(1);    writeln(ans);  end;end.


0 0