hdu 1800 Flying to the Mars 字典树

题目:给出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.


你可能感兴趣的:(hdu 1800 Flying to the Mars 字典树)