【字典序+栈】接龙游戏(words.pas/in/out)

 

接龙游戏

(words.pas/in/out)

Problem

给出n个单词,已经按长度排好了序.如果单词I是单词J的前缀,那么I- J算一次接龙.

你的任务是:对于输入的单词,找出最长的龙.

Input

数据第一行为n(1<=n<=100000),以下n行每行是一个单词(由小写组成),已经按长度排好了序.每个单词的长度不超过50.

Output

输出一行,这行为一个数,即最长的龙的长度.

Sample Input

5

i

a

int

able

inter

Sample Input

3

===================

这道题一测的时候,我全超时

那时我是直接用DP..并没有任何的排序..

----------------------------------------------------

其实这道题可以先按字典序排了之后再维护一个栈就可以了..

以后要记住了...

---------------------------------------------------------------------------------

考试时还想到了一种方法..==做..

建一棵树...

保证左子树并不是根点的后缀,右子树为根节点的后缀...

 

==============================================

 

var
  n:longint;
  s,s_z:array[1..100000]of string;
  s_t:longint;
  ans:longint;
 // f:array[1..100000]of longint;
procedure init;
begin
  assign(input,'words.in');
  assign(output,'words.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

function pd(x,y:longint):boolean;
var
  i:longint;
begin
  pd:=true;
  for i:=1 to length(s[x]) do
    if s[x][i]<>s[y][i] then exit(false);
end;

procedure qsort(l,r:longint);
var
  i,j:longint;
  x,tem:string;
begin
  i:=l; j:=r;
  x:=s[(l+r)shr 1];
  repeat
    while x<s[j] do dec(j);
    while s[i]<x do inc(i);
    if i<=j then
      begin
        tem:=s[i];
        s[i]:=s[j];
        s[j]:=tem;
        inc(i); dec(j);
      end;
  until i>j;
  if i<r then qsort(i,r);
  if l<j then qsort(l,j);
end;

function pd(s1,s2:string):boolean;
var
  i:longint;
begin
  pd:=true;
  for i:=1 to length(s1) do
    if s1[i]<>s2[i] then exit(false);
end;

procedure ru(i:longint);
begin
  if s_t=0 then
    begin
      inc(s_t);
      s_z[s_t]:=s[i];
      if s_t>ans then ans:=s_t;
    end
    else
    begin
      while (s_t>=1) and not pd(s_z[s_t],s[i]) do dec(s_t);
      inc(s_t);
      s_z[s_t]:=s[i];
      if s_t>ans then ans:=s_t;
    end;
end;

procedure main;
var
  i:longint;
begin
  readln(n);
  for i:=1 to n do
    begin
      readln(s[i]);
     // f[i]:=1;
    end;
  qsort(1,n);
  s_t:=0;
  ans:=0;
  for i:=1 to n do
    begin
      ru(i);
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值