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

    你可能感兴趣的文章
    PowerDesigner导出Report通用报表
    查看>>
    PowerDesigner教程系列(二)概念数据模型
    查看>>
    Powerdesigner显示表的comment和列的comment的方法
    查看>>
    PowerDesigner最基础的使用方法入门学习
    查看>>
    PowerDesigner版本控制器设置权限
    查看>>
    PowerDesigner生成数据模型并导出报告
    查看>>
    QGIS中导入dwg文件并使用GetWKT插件获取绘制元素WKT字符串以及QuickWKT插件实现WKT显示在图层
    查看>>
    PowerDesigner逆向工程从SqlServer数据库生成PDM(图文教程)
    查看>>
    PowerEdge T630服务器安装机器学习环境(Ubuntu18.04、Nvidia 1080Ti驱动、CUDA及CUDNN安装)
    查看>>
    PowerPC-object与elf中的符号引用
    查看>>
    QFileSystemModel
    查看>>
    Powershell DSC 5.0 - 参数,证书加密账号,以及安装顺序
    查看>>
    PowerShell 批量签入SharePoint Document Library中的文件
    查看>>
    Powershell 自定义对象小技巧
    查看>>
    pytorch从预训练权重加载完全相同的层
    查看>>
    PowerShell~发布你的mvc网站
    查看>>
    PowerShell使用详解
    查看>>
    Powershell制作Windows安装U盘
    查看>>
    powershell命令
    查看>>
    Powershell如何查看本地公网IP
    查看>>