• BZOJ 1031: [JSOI2007]字符加密Cipher 后缀数组


    原题链接:

    题解:

    就把字符串扩大一倍后跑一发后缀数组即可。

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #define INF 2*0x3f3f3f3f
    
    using namespace std;
    const int maxn = 200051; //注意数组的大小,记得更改
    
    int wa[maxn], wb[maxn], wv[maxn], wss[maxn];
    int cmp(int *r, int a, int b, int l) {
        return r[a] == r[b] && r[a + l] == r[b + l];
    }
    void da(int *r, int *sa, int n, int m) { //r为所求取的转化字符串 sa为求得的sa数组  n为数组长度+1  m为数组的最大值+1
        int i, j, p, *x = wa, *y = wb, *t;
        for (i = 0; i < m; i++) wss[i] = 0;
        for (i = 0; i < n; i++) wss[x[i] = r[i]]++;
        for (i = 1; i < m; i++) wss[i] += wss[i - 1];
        for (i = n - 1; i >= 0; i--) sa[--wss[x[i]]] = i;
        for (j = 1, p = 1; p < n; j *= 2, m = p) {
            for (p = 0, i = n - j; i < n; i++) y[p++] = i;
            for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
            for (i = 0; i < n; i++) wv[i] = x[y[i]];
            for (i = 0; i < m; i++) wss[i] = 0;
            for (i = 0; i < n; i++) wss[wv[i]]++;
            for (i = 1; i < m; i++) wss[i] += wss[i - 1];
            for (i = n - 1; i >= 0; i--) sa[--wss[wv[i]]] = y[i];
            for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
        }
        return;
    }
    
    int ranking[maxn], height[maxn];
    void build_height(int *r, int *sa, int n) { //r为求得的转化原始数组,sa为已经求得的数组,n为len
        int i, j, k = 0;
        for (i = 1; i <= n; i++) ranking[sa[i]] = i;
        for (i = 0; i < n; height[ranking[i++]] = k) {
            for (k ? k-- : 0, j = sa[ranking[i] - 1]; r[i + k] == r[j + k]; k++);
        }
    }
    
    int sa[maxn], r[maxn];
    
    string s;
    int str[maxn];
    
    int main() {
        //freopen("1031.in","r",stdin);
        //freopen("1031.out","w",stdout);
        //cin.sync_with_stdio(false);
        cin >> s;
        int n = s.length();
        s = s + s;
        for (int i = 0; i < s.length(); i++)str[i] = s[i] + 2;
        str[s.length()]=1;
        da(str, sa, s.length() + 1, 230);
        for (int i = 0; i <= s.length(); i++) {
            if(sa[i]>=n)continue;
            int p = sa[i] + n - 1;
            cout << s[p];
        }
        cout << endl;
        return 0;
    }
  • 相关阅读:
    Ubuntu18.04可执行文件运行提示No such file or directory
    Linux gcc(ar命令)打包库到另一个库中的另外一种方法
    干干净净的grep
    C语言里面和时间有关的函数
    Ubuntu上安装tftp服务
    因为新冠,宅家2周,折腾了一下电视盒子。
    批量处理文件的Python程序
    Windows 10中使用VirtualBox
    重采样Resample 的一些研究记录。
    微信公众号接入第三方服务器,设置自动回复、关键回复、自定义菜单,配置及开发流程
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4847707.html
Copyright © 2020-2023  润新知