如果在黑暗爆炸过了但是在SPOJ WA掉了的话
查看原帖
如果在黑暗爆炸过了但是在SPOJ WA掉了的话
195913
tudouuuuu楼主2020/11/15 17:26

因为自己准备的后缀数组模板对oldrk和rk的 [len+1,n2][len+1, n*2] 部分进行初始化导致能过掉单组样例但是多组样例过不去。

如果在黑暗爆炸下载数据重复填装 8.in10.in 的话,会看到非常诡异的数字出现。

参考代码:

错误的:

namespace SA {
    int len;
    int sa[MAXN], rk[MAXN << 1], oldrk[MAXN << 1], id[MAXN], cnt[MAXN];

    void run(char s[], int _len) {   // call: run(str, strlen(str+1));
        len = _len;
        int m = max(len, 300);
        // memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i <= m; i++) cnt[i] = 0;
        for (int i = 1; i <= len; i++) ++cnt[rk[i] = s[i]];
        for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
        for (int i = len; i >= 1; i--) sa[cnt[rk[i]]--] = i;

        for (int w = 1; w <= len; w <<= 1) {
            // memset(cnt, 0, sizeof(cnt));
            for (int i = 0; i <= m; i++) cnt[i] = 0;
            for (int i = 1; i <= len; i++) id[i] = sa[i];
            for (int i = 1; i <= len; i++) ++cnt[rk[id[i] + w]];
            for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) sa[cnt[rk[id[i] + w]]--] = id[i];
            for (int i = 0; i <= m; i++) cnt[i] = 0;
            // memset(cnt, 0, sizeof(cnt));
            for (int i = 1; i <= len; i++) id[i] = sa[i];
            for (int i = 1; i <= len; i++) ++cnt[rk[id[i]]];
            for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) sa[cnt[rk[id[i]]]--] = id[i];
            // memcpy(oldrk, rk, sizeof(rk));
            for (int i = 0; i <= len; i++) oldrk[i] = rk[i];
            for (int p = 0, i = 1; i <= len; i++) {
                if (oldrk[sa[i]] == oldrk[sa[i - 1]] && oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]) rk[sa[i]] = p;
                else rk[sa[i]] = ++p;
            }
        }
    }

    void get_height(char s[]) {    // step2 call: get_height(str)
        int k = 0;
        for (int i = 1; i <= len; i++) rk[sa[i]] = i;
        for (int i = 1; i <= len; i++) {
            if (rk[i] == 1) continue;
            if (k) --k;
            int j = sa[rk[i] - 1];
            while (j + k <= len && i + k <= len && s[i + k] == s[j + k]) k++;
            height[rk[i]] = k;
        }
    }
}

正确的:

namespace SA {
    int len;
    int sa[MAXN], rk[MAXN << 1], oldrk[MAXN << 1], id[MAXN], cnt[MAXN];

    void run(char s[], int _len) {   // call: run(str, strlen(str+1));
        len = _len;
        int m = max(len, 300);
        // memset(cnt, 0, sizeof(cnt));
        for (int i = 0; i <= m; i++) cnt[i] = 0;
        for (int i = 1; i <= len; i++) ++cnt[rk[i] = s[i]];
        for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
        for (int i = len; i >= 1; i--) sa[cnt[rk[i]]--] = i;

        for (int i = len+1; i <= (len<<1); i++) oldrk[i] = rk[i] = 0;   // 这里!
        
        for (int w = 1; w <= len; w <<= 1) {
            // memset(cnt, 0, sizeof(cnt));
            for (int i = 0; i <= m; i++) cnt[i] = 0;
            for (int i = 1; i <= len; i++) id[i] = sa[i];
            for (int i = 1; i <= len; i++) ++cnt[rk[id[i] + w]];
            for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) sa[cnt[rk[id[i] + w]]--] = id[i];
            for (int i = 0; i <= m; i++) cnt[i] = 0;
            // memset(cnt, 0, sizeof(cnt));
            for (int i = 1; i <= len; i++) id[i] = sa[i];
            for (int i = 1; i <= len; i++) ++cnt[rk[id[i]]];
            for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
            for (int i = len; i >= 1; i--) sa[cnt[rk[id[i]]]--] = id[i];
            // memcpy(oldrk, rk, sizeof(rk));
            for (int i = 0; i <= len; i++) oldrk[i] = rk[i];
            for (int p = 0, i = 1; i <= len; i++) {
                if (oldrk[sa[i]] == oldrk[sa[i - 1]] && oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]) rk[sa[i]] = p;
                else rk[sa[i]] = ++p;
            }
        }
    }

    void get_height(char s[]) {    // step2 call: get_height(str)
        int k = 0;
        for (int i = 1; i <= len; i++) rk[sa[i]] = i;
        for (int i = 1; i <= len; i++) {
            if (rk[i] == 1) continue;
            if (k) --k;
            int j = sa[rk[i] - 1];
            while (j + k <= len && i + k <= len && s[i + k] == s[j + k]) k++;
            height[rk[i]] = k;
        }
    }
}
2020/11/15 17:26
加载中...