poj2138

【题意】

给定一个单词库,有一个起始单词,从这个单词出发,每次在任意位置加一个任意字母变成另外一个单词,问最多能加几次,输出最长单词

【输入】

第一行n 起始单词

接下来n行每行一个单词

【输出】

最长单词,数据保证唯一


按长度排下序,试试长度相差1的两个点是否能转换,可以转换连一条边,然后做spfa,输出距离最远的点


program poj2138;
var
  ans,tot,st,n,i,j,k:longint;
  fin:array [0..81] of longint;
  root,dis:array [0..1001] of longint;
  dl:array [0..2001] of longint;
  next,point:array [0..200001] of longint;
  str:array [0..1001] of string;
  sta:string;
  space:char;

procedure swap (var a,b:string);inline;
var
  i:string;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure qsort (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=length(str[(s+e) div 2]);
  while i<=j do
    begin
      while length(str[i])<k do inc(i);
      while length(str[j])>k do dec(j);
      if i>j then break;
      swap(str[i],str[j]);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

procedure connect (u,v:longint);inline;
begin
  inc(tot);
  point[tot]:=v;
  next[tot]:=root[u];
  root[u]:=tot;
end;

function ok (a,b:longint):boolean;
var
  i:longint;
begin
  for i:=1 to length(str[b]) do
    if str[a]=copy(str[b],1,i-1)+copy(str[b],i+1,length(str[b])-i) then exit(true);
  exit(false);
end;

begin
  readln(n,space,sta);
  for i:=1 to n do
    readln(str[i]);
  qsort(1,n);
  for st:=1 to n do
    if str[st]=sta then break;
  i:=1;
  while i<=n do
    begin
      k:=length(str[i]);
      while length(str[i])=k do inc(i);
      fin[k]:=i-1;
    end;
  for i:=1 to n do
    for j:=fin[length(str[i])]+1 to fin[length(str[i])+1] do
      if ok(i,j) then connect(i,j);
  fillchar(dis,sizeof(dis),63);
  tot:=1;
  i:=1;
  dl[1]:=st;
  dis[st]:=1;
  ans:=st;
  while i<=tot do
    begin
      k:=root[dl[i]];
      while k<>0 do
        begin
          if dis[point[k]]>dis[dl[i]]+1 then
            begin
              dis[point[k]]:=dis[dl[i]]+1;
              if dis[point[k]]>dis[ans] then ans:=point[k];
              inc(tot);
              dl[tot]:=point[k];
            end;
          k:=next[k];
        end;
      inc(i);
    end;
  writeln(str[ans]);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值