后缀数组实现

先贴这里,免得忘了

program sa;
type int=longint;
var
        i,j,k,m,n,l,max:int;
        a,b,c,d,x,r:array[0..1000000]of int;
        ch:char;

procedure main;
begin
        l:=1;
        repeat
                for i:=0 to max do begin b[i]:=0;c[i]:=0;end;
                for i:=1 to n do begin inc(b[a[i]]);inc(c[a[i+l]]);end;
                for i:=1 to max do begin inc(b[i],b[i-1]);inc(c[i],c[i-1]);end;

                for i:=1 to n do begin d[c[a[i+l]]]:=i;dec(c[a[i+l]]);end;
                for i:=n downto 1 do begin k:=d[i];r[b[a[k]]]:=d[i];dec(b[a[k]]);end;
                max:=0;
                for i:=1 to n do begin
                        if(a[r[i-1]]<>a[r[i]])or(a[r[i-1]+l]<>a[r[i]+l])then inc(max);
                        x[r[i]]:=max;
                end;
                for i:=1 to n do a[i]:=x[i];
                l:=l<<1;
        until max=n;
end;

begin
        assign(input,'sa.in');reset(input);
        assign(output,'sa.out');rewrite(output);
        while not eoln do begin
                inc(n);read(ch);a[n]:=ord(ch);
                if a[n]>max then max:=a[n];
        end;
        main;
        for i:=1 to n do writeln(a[i]);
        close(input);close(output);
end.

如果使用指针实现X,A的功能就可以少一个循环,应该会更快一点

最长公共子串:

program sa;
type int=longint;
var
        l,i,j,k,m,n,max,ans:int;
        a,b,c,d,r,x,h,st:array[0..500000]of int;
        ch:char;

procedure main;
begin
        l:=1;max:=200;
        repeat
                for i:=0 to max do begin c[i]:=0;b[i]:=0;end;
                for i:=1 to n do begin inc(b[a[i]]);inc(c[a[i+l]]);end;
                for i:=1 to max do begin inc(b[i],b[i-1]);inc(c[i],c[i-1]);end;

                for i:=1 to n do begin d[c[a[i+l]]]:=i;dec(c[a[i+l]]);end;
                for i:=n downto 1 do begin r[b[a[d[i]]]]:=d[i];dec(b[a[d[i]]]);end;

                max:=0;
                for i:=1 to n do begin
                        if(a[r[i]]<>a[r[i-1]])or(a[r[i]+l]<>a[r[i-1]+l])then inc(max);
                        x[r[i]]:=max;
                end;
                for i:=1 to n do a[i]:=x[i];
                l:=l<<1;
        until max=n;
        for i:=1 to n do b[a[i]]:=i;
        for i:=1 to n do begin
                if h[i-1]>0 then h[i]:=h[i-1]-1;
                while st[b[a[i]-1]+h[i]]=st[i+h[i]] do inc(h[i]);
        end;
        for i:=1 to n do x[a[i]]:=h[i];
        for i:=2 to n do if((b[i]<m)xor(b[i-1]<m))and(ans<x[i])
                then ans:=x[i];
end;//a->rank,b->sa,h->h,x->height

begin
        assign(input,'data.txt');reset(input);
        assign(output,'ans.txt');rewrite(output);
        while not eoln do begin read(ch);inc(n);st[n]:=ord(ch);end;
        m:=n+1;readln;
        inc(n);st[n]:=200;
        while not eoln do begin read(ch);inc(n);st[n]:=ord(ch);end;
        a:=st;main;
        write(ans);
        close(input);close(output);
end.


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值