博客
关于我
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/

    你可能感兴趣的文章
    Python 从入门到精通:30天速成教程到底有多狠?你能坚持下来吗?
    查看>>
    Python 从数据库中存储和检索密码的最安全方法
    查看>>
    Python语言及其应用 - 知识点遍历
    查看>>
    Python 优化提速的 8 个小技巧
    查看>>
    Python 余弦相似度与皮尔逊相关系数 计算
    查看>>
    python 使用execjs 报编码错误解决办法,UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xac in position 145: il
    查看>>
    python 使用filetype校验文件
    查看>>
    Python 使用flush函数将缓冲区数据立即写磁盘
    查看>>
    python 使用in判断不准确,in不好使
    查看>>
    Python 使用pandas 进行查询和统计详解
    查看>>
    Redis 配置文件redis.conf详细解释
    查看>>
    python网络爬虫(2)——scrapy框架的基础使用
    查看>>
    python网络爬虫实例教程试读_Python网络爬虫实战教程(全套完整版) - 学途无忧网 - 做技术的王者 - Powered By EduSoho...
    查看>>
    Python 使用哈希函数用于加密
    查看>>
    Python 依赖管理的革新——Poetry 深度解析
    查看>>
    python 保留精度及增加去除数字的千位分隔符(金额化数字)
    查看>>
    python 倒计时 9,8,7,。。。。。。0
    查看>>
    Python 入门开发学习笔记之数据的增删改查
    查看>>
    Python 入门教程(2)搭建环境 2.4、VSCode配置Node.js运行环境
    查看>>
    Python 八大排序算法合集
    查看>>