【题意】
给定一些字符串,询问最长的“链”,“链”就是一些长度相差为1的字符串,且长度差为1的两个字符串长的那个删掉一个字符就跟短的构成(含有各个字母的个数)一样了
求最长链,任意输出一个即可
【输入】
若干行,每行一个字符处
【输出】
从短到长输出字符串
这道题将所有字符串按长度排序从长到短进行dp
对于每个字符串hash一下,枚举当前串加一个字符的字符串,然后hash判断有没有,有了将通往的值+1看是不是比当前最优长,再记一下最优从哪来的
hash必须记录hash值对应的字符串,数据很威武,直接搞重合率略高
program poj2004; const maxn=5466123; k=37; var ans,max,min,n,i,j:longint; quick:array ['a'..'z'] of longint; root,st:array [0..10001] of string[20]; long,last,f,dl:array [0..10001] of longint; rehash:array [0..maxn] of longint; anti:array [0..maxn] of string[20]; temp:char; procedure swap (var a,b:longint);inline; var i:longint; begin i:=a; a:=b; b:=i; end; function sort (now:string):string;inline; var i,j,l:longint; temp:char; begin l:=length(now); for i:=1 to l-1 do for j:=i+1 to l do if now[i]>now[j] then begin temp:=now[i]; now[i]:=now[j]; now[j]:=temp; end; exit(now); end; procedure qsort (s,e:longint); var i,j,k:longint; begin if s>=e then exit; i:=s; j:=e; k:=dl[(s+e) div 2]; while i<=j do begin while long[dl[i]]<long[k] do inc(i); while long[dl[j]]>long[k] do dec(j); if i>j then break; swap(dl[i],dl[j]); inc(i); dec(j); end; qsort(s,j); qsort(i,e); end; function hash (now:string):longint;inline; var i:longint; s:longint; begin s:=0; for i:=1 to length(now) do begin s:=s+quick[now[i]]; if s>=maxn then s:=s-maxn; end; now:=sort(now); while (rehash[s]<>0)and(anti[s]<>now) do begin inc(s); if s=maxn then s:=s-maxn; end; exit(s); end; begin quick['a']:=173; for temp:='b' to 'z' do quick[temp]:=(quick[pred(temp)]*(k+ord(temp))) mod maxn; max:=-maxlongint; min:=maxlongint; n:=0; while not seekeof do begin inc(n); readln(root[n]); long[n]:=length(root[n]); if long[n]>max then max:=long[n]; if long[n]<min then min:=long[n]; dl[n]:=n; end; qsort(1,n); for i:=1 to n do begin j:=hash(root[dl[i]]); rehash[j]:=i; anti[j]:=sort(root[dl[i]]); end; ans:=n; for i:=n downto 1 do begin f[i]:=1; last[i]:=0; if long[dl[i]]=long[dl[n]] then continue; for temp:='a' to 'z' do begin j:=hash(root[dl[i]]+temp); if (rehash[j]<>0)and(rehash[j]>i)and(f[rehash[j]]+1>f[i]) then begin f[i]:=f[rehash[j]]+1; last[i]:=rehash[j]; end; end; if f[i]>f[ans] then ans:=i; if f[i]=max-min+1 then break; end; i:=ans; repeat writeln(root[dl[i]]); i:=last[i]; until i=0; end.