社区讨论

求助大佬

P3809【模板】后缀排序参与者 7已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@mi7pncqt
此快照首次捕获于
2025/11/21 01:33
4 个月前
此快照最后确认于
2025/11/21 01:33
4 个月前
查看原帖
对比: 第一个点:
WA\text{WA}
PASCAL
// 后缀排序

Uses math;

Const total=1010; // 这个不在意

var
    sa,tmp,num,pus,copy,area,place,bucket,ranking:array[-1..total] of longint;
    reach,from,next,cnt:array[-1..total] of longint;
    queue:array[-1..11,-1..total,-1..3] of longint;
    rank:array[-1..total,-1..3] of longint;
    lg:array[-1..30] of longint;
    i,n,tot,tail,number,border:longint;
    s:ansistring;
    j:char;

procedure add(l,r:longint);
begin inc(tot); from[tot]:=l; reach[tot]:=r; next[tot]:=cnt[l]; cnt[l]:=tot; end;

procedure Radix;
var
    i,j,l,k,maxn:longint;
    s:string;
begin
    maxn:=-maxlongint;
    for i:=1 to tail do
    begin
        maxn:=max(pus[i],maxn); copy[i]:=pus[i]; place[i]:=i; ranking[copy[i]]:=maxlongint;
    end; str(maxn,s);
    for i:=1 to length(s) do
    begin
        for j:=0 to 9 do queue[j,0,0]:=0;
        for j:=1 to tail do
        begin
            k:=pus[j] mod 10; pus[j]:=pus[j] div 10;
            inc(queue[k,0,0]);
            queue[k,queue[k,0,0],1]:=pus[j];
            queue[k,queue[k,0,0],2]:=place[j];
        end; k:=0;
        for j:=0 to 9 do
            for l:=1 to queue[j,0,0] do
            begin
                inc(k); pus[k]:=queue[j,l,1]; place[k]:=queue[j,l,2];
                queue[j,l,1]:=0; queue[j,l,2]:=0;
            end;
    end;
    // 去重开始
    for i:=1 to tail do ranking[copy[i]]:=min(ranking[copy[i]],place[i]);
    for i:=1 to tail do place[i]:=ranking[copy[i]];
end;

procedure Sort;
var i,j,k,l,maxn,number:longint;
begin
	// 第一关键字排序开始
    for i:=1 to n do inc(bucket[num[i]]);
    for i:=1 to border do inc(bucket[i],bucket[i-1]); border:=0;
    for i:=1 to n do begin rank[i,1]:=bucket[num[i]]; border:=max(border,rank[i,1]); end;
    i:=0;
    repeat
        inc(i); tot:=0; number:=0;
        // 清空数组开始
        filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1);
        fillchar(bucket,sizeof(bucket),0);
        fillchar(reach,sizeof(reach),0);
        fillchar(from,sizeof(from),0);
        fillchar(next,sizeof(next),0);
        // 生成第二关键字开始
        for k:=1 to n do rank[k,2]:=rank[k+lg[i],1];
        // 第一关键字排序开始 (桶+链表)
        for k:=1 to n do if bucket[rank[k,1]]>0 then add(bucket[rank[k,1]],k) else bucket[rank[k,1]]:=k; 
        // 第二关键字排序开始 (基数排序)
        for k:=1 to border do
        begin
            if bucket[k]=0 then continue;
            // 存储第二关键字开始
            tail:=1; j:=cnt[bucket[k]]; pus[1]:=rank[bucket[k],2]; area[1]:=bucket[k];
            while j<>-1 do begin inc(tail); area[tail]:=reach[j]; pus[tail]:=rank[reach[j],2]; j:=next[j]; end;
            // 基数排序开始
            Radix; maxn:=0;
            // 统计答案开始
            for j:=1 to tail do begin rank[area[j],1]:=place[j]+number; maxn:=max(maxn,rank[area[j],1]); end;
            number:=maxn;
        end;
    until lg[i+1]>n;
end;

begin
    filldword(rank,sizeof(rank) div 4,0);
    for i:=1 to 25 do lg[i]:=1 << (i-1);
    readln(s); n:=length(s); number:=0;
    // 离散化开始
    for j:='0' to '9' do begin inc(number); tmp[ord(j)]:=number; end;
    for j:='A' to 'Z' do begin inc(number); tmp[ord(j)]:=number; end;
    for j:='a' to 'z' do begin inc(number); tmp[ord(j)]:=number; end;
    for i:=1 to n do num[i]:=tmp[ord(s[i])]; border:=total; Sort;
    // for i:=1 to n do writeln(rank[i,1]);
    // 统计答案开始
    for i:=1 to n do sa[rank[i,1]]:=i;
    for i:=1 to n do write(sa[i],' ');
end.

回复

7 条回复,欢迎继续交流。

正在加载回复...