• 后缀数组(基数排序)的具体分析


    我看后缀数组,思想很容易懂,但是基数排序那边我确实理解了很久才理解,现在我写一份自己可以看懂的具体分析。

    第一步,首先将所有的位置上的值装入数组中,并记录排名为i的数为sa[i],第i个数的排名为rank[i].

    下面就要进行logn次的倍增操作,我们定义k为当前倍增长度

    基数排序,痛苦ing

    首先将每一对数的排名存到cur数组,cur[i][0]记录初始位置的排名,cur[i][1]为i+k位置上的排名

    首先我们对第二关键字也就是cur[i][1]进行排名,用sa数组记录排名为i的在第几个

    接下来,我们就对第一关键字进行排序,注意加入顺序为sa数组,这样可以保证,第一关键字一定时,排名小的一定在前面,从而保证了排序顺序,然后再按第一关键字进行加入。用链表处理会更容易懂一些

    只能说白书上的代码真心看不懂,我对某位同学的程序加了一下注释,应该可以看懂。

     1 void Suffix_Array()
     2 {
     3     N++;
     4     rep(i, 0, N - 1) SA[i] = i;//初始排名 
     5     sort(SA, SA + N, cmp);//根据位置排序 
     6     rep(i, 1, N - 1) Rank[SA[i]] = (s[SA[i]] > s[SA[i - 1]]) ? i : Rank[SA[i - 1]];//记录每个点的排名 
     7     for (int k = 1; ; k <<= 1)//枚举长度 
     8     {
     9         rep(i, 0, N - 1) Cur[i][0] = Rank[i], Cur[i][1] = (i + k < N) ? Rank[i + k] : 0;//每一对点的排名 
    10         rep(i, 0, N) E[i].clear();
    11         rep(i, 0, N - 1) E[Cur[i][1]].push_back(i);//将所有排名一样的点加入链表 
    12         for (int i = N, n = 0; i >= 0; --i)
    13             for (int j = E[i].size() - 1; j >= 0; --j) SA[n++] = E[i][j];  //重新排名,大的在前,小的在后 
    14         rep(i, 0, N) E[i].clear();
    15         rep(i, 0, N - 1) E[Cur[SA[i]][0]].push_back(SA[i]);//加入当前点的排名,保证排名小的在后面 
    16         for (int i = 0, n = 0; i <= N; ++i)
    17             for (int j = E[i].size() - 1; j >= 0; --j) SA[n++] = E[i][j];//最终排名 
    18         //memset(Rank, 0, sizeof(Rank));
    19         int Indep = 1;
    20         rep(i, 1, N - 1)
    21             if (Cur[SA[i]][0] == Cur[SA[i - 1]][0] && Cur[SA[i]][1] == Cur[SA[i - 1]][1])
    22                 Rank[SA[i]] = Rank[SA[i - 1]], Indep = 0; else Rank[SA[i]] = i;//重新排名 
    23         if (Indep) break;
    24     }
    25 }
    View Code
  • 相关阅读:
    Python open 读和写
    Sublime Text的使用
    解决MySQL Workbench导出乱码问题
    统计学(一)
    pymysql使用(二)
    使用pymysql(使用一)
    2个Excel表格核对技巧
    用Python读写Excel文件的方式比较
    从零上手Python关键代码
    php面试
  • 原文地址:https://www.cnblogs.com/sillygirl/p/3911893.html
Copyright © 2020-2023  润新知