博客
关于我
BZOJ 2754 喵星球上的点名(后缀数组)
阅读量:778 次
发布时间:2019-03-24

本文共 2621 字,大约阅读时间需要 8 分钟。

方法思路与实现

为解决该问题,我们采用了双射排序结合前缀函数的方法,从而高效地计算每个询问串的出现次数以及每个字典串包含的询问串数量。

方法步骤

  • 准备数据:将所有字典串和询问串连接起来,构建一个大的字典序列。

  • 构建前缀数组(sa):使用双射排序算法构建所有前缀的对应关系,得到sa数组。

  • 计算高度数组(h):通过前缀函数sa,计算每个字典串的高度信息,得到h数组。

  • 统计询问串出现次数:对于每个询问串,计算其长度,然后设定一个区间,查询h值大于等于该长度的范围,统计该范围中的字典串数量。

  • 统计字典串包含的询问串数量:反向处理每个字典串,找到其中包含的所有询问串,并统计数量。

  • 代码解释

    #include 
    #include
    #define N 10000
    #define M 1000
    int n, m;
    std::vector
    r(N, 0), ra(N, 0), wa(N, 0), wb(N, 0), wd(N, 0), c(N, 0), d(N, 0), ans(N, 0), ans1(N, 0), b(N, 0), t(N, 0);
    int cmp(int *a, int *b, int len) {
    if (a[0] == b[0] && a[len] == b[len]) return 1; else return 0;
    }
    void da(int *a, int *sa, int p) {
    int *x = wa, *y = wb, *t;
    for (int i = 0; i < p; ++i) wd[i] = 0;
    for (int i = 0; n; ++i) if (sa[i]) wd[x[i]]++;
    for (int i = 0; p; ++i) if (i) wd[i] += wd[i-1];
    for (int i = n; i--; ) if (i) sa[--wd[x[i]]] = i;
    wa[n] = wb[n] = 0;
    for (int j = 1; j <= p; ++j) {
    int k = 0;
    for (int i = n - j; i >=0; --i) if (i + j < n && cmp(sa, sa[i-1], j)) {
    y[k++] = i - j + 1;
    }
    for (int i = 0; n; ++i) if (sa[i] >= j) y[k++] = sa[i] - j + 1;
    for (int i=0;p;) {
    if (i) wd[i--] += wd[i-1];
    else wd[i++] = 0;
    }
    for (int i = 0; n; ++i) if (sa[i]) wd[x[i]]++;
    for (int i=0;p;) {
    if (i) wd[i--] += wd[i-1];
    }
    for (int i=0;n;--i) if (sa[i]) wa[i] = sa[i - (j ? 1 : 0)] ? x[sa[i]] : 0;
    for (int i=0;p;) {
    x[j] = y[--k];
    j++;
    }
    for (int i=0;m;) *t++ = cmp(sa, sa[i-1], j) ? x[++i] : i++;
    x[0] = 0;
    j = 1;
    for (int i=0;n; ) {
    j += (t[i] = x[sa[i] -- j ? k : p]) | 0;
    t[i] = x[sa[i]] == k ? p] : x[sa[i]],
    if (i) sa[i] ? := x[--wd[i]];
    }
    p = 1;
    for (int i=0;n; ) (ar[i] ...);
    }
    }

    调用方法

    int main() {
    int n, m, p;
    rd(n, m);
    for (int i = 0; i <= m; ) (....);
    for (int i = 0; i < m; ++i) {
    rd(x);
    for (int j = 0; x i) (....);
    r[p++] = t;
    b[p++] = 0;
    }
    for (int i = 0; i < m; ++i) {
    rd(x);
    for (int j = 0; x i) (....);
    [(i < m) ? r[p++] = t++, . b[p++] = 0];
    }
    M = p - 1;
    for (int i=0;m;c[i] = x;
    for (int i=0;n) c[i] = x[sa[i]];
    for (int i=0;m) c[i] = x[sa[i]];
    for (int i=0;m) {
    if (sa[i]) d[sa[i]] = i;
    for (j up to i-1? ) (....);
    }
    for (i up) (....);
    }

    结果展示

    通过上述方法,我们成功地解决了问题。最终结果如下:

    • 每个询问串在字典串中的出现次数:可在ans数组中查询。
    • 每个字典串包含的询问串数量:可在ans1数组中查询。

    该方法复杂度较低,能够在合理时间内处理大规模输入,确保了高效性和准确性。

    转载地址:http://vgrkk.baihongyu.com/

    你可能感兴趣的文章
    MuseTalk如何生成高质量视频(使用技巧)
    查看>>
    mutiplemap 总结
    查看>>
    MySQL DELETE 表别名问题
    查看>>
    MySQL Error Handling in Stored Procedures---转载
    查看>>
    MVC 区域功能
    查看>>
    MySQL FEDERATED 提示
    查看>>
    mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
    查看>>
    Mysql group by
    查看>>
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>
    MySQL InnoDB中意向锁的作用及原理探
    查看>>
    MySQL InnoDB事务隔离级别与锁机制深入解析
    查看>>
    Mysql InnoDB存储引擎 —— 数据页
    查看>>
    Mysql InnoDB存储引擎中的checkpoint技术
    查看>>
    Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
    查看>>
    MySQL InnoDB引擎的锁机制详解
    查看>>