回 帖 发 新 帖 刷新版面

主题:[原创]pku acm 1147 Binary codes

a××......× ch    ch a××......×
       ...        = 
z××......× ch    ch z××......×
( [i]ch[/i] 是个字符)


如果能知道左旋后对应的行数,就能找出第一行。例如:
1: 0 0 1 0 1        1: 0 0 1 0 1
2: 0 1 0 1 0        4: 0 1 0 0 1
3: 1 0 1 0 0    →  2: 0 1 0 1 0
4: 0 1 0 0 1        5: 1 0 0 1 0
5: 1 0 0 1 0        3: 1 0 1 0 0

(b1 b2  …… bn-1 bn) 左旋后得 (b2 b3 …… bn b1)
如果知道第一行左旋后对应排序矩阵的第三行,即知道第三行的最后一个为b1,即0;同理,
第二行左旋后对应排序矩阵的第五行,即知道第五行的最后一个为b2,即0;
第三行左旋后对应排序矩阵的第二行,即知道第五行的最后一个为b3,即1;
第四行左旋后对应排序矩阵的第四行,即知道第五行的最后一个为b4,即0;
第五行左旋后对应排序矩阵的第一行,即知道第五行的最后一个为b5,即1。

假设排序矩阵中两行都以0开始,则它们左旋后,前后次序不变(因为是排过序的),所以在矩阵中以0开始的第1行,它的左旋后的序列在最后一列的第一个0的行。对1开始的行有同样的性质。
例:         next
1: 0       1   3
2: 0       1   4
3: 0 →    0   5
4: 1       0   1
5: 1       0   2

// 1147 Binary codes
# include <iostream>
using namespace std;
const int N = 3001;
int main()
{
    int n;
    cin >> n;
    int digits[N], next[N];
    int counter = 0, i;
    for (i = 1; i <= n; ++i) {
        cin >> digits[i];
        if (digits[i] == 0) {
            ++counter;
        }
    }
    int zero = 1, one = counter + 1;
    for (i = 1; i <= n; ++i) {
        if (digits[i] == 0) {
            next[zero++] = i;
        } else {
            next[one++] = i;
        }
    }
    int ptr = 1;
    for (i = 1; i <= n; ++i) {
        ptr = next[ptr];
        cout << digits[ptr] << " ";
    }
    cout << endl;
    return 0;
}

[url=http://blog.csdn.net/Sedgewick]感兴趣的来我的窝看看。[/url]

回复列表 (共1个回复)

沙发

今天才知道,这原来是赫赫有名的 The Burrows-Wheeler transform (块排序压缩)。
bzip2就是用这个原理做出来的。

[url=http://www.answers.com/Burrows-Wheeler%20transform]Burrows-Wheeler transform[/url]

我来回复

您尚未登录,请登录后再回复。点此登录或注册