一道很難的有關演算法的測試題,寫逆演算法
轉載 來源:http://blog.liutaotao.com/blogview.asp?logID=38
最近在學習壓縮演算法,剛學懂了一個壓縮演算法,把它加以改造,做成了一道測試題.
這道題很難,這個演算法很巧.如果不知道答案,我都沒有把握能做出來.
如果你自信演算法方面很強,可以試一試.如果你做不出來,又想知道答案,聯絡我.
以下已經給出了完整的 Decode 代碼,Encode 代碼有幾處空,填入代碼,使演算法工作.
這個演算法可以廣泛地應用於註冊機,網路傳輸等方面.
#include <Windows.h>
#include <stdio.h>
class CBitEncoder
{
PBYTE m_pbuf;
UINT m_len;
UINT Prob;
UINT _cacheSize;
BYTE _cache;
UINT64 Low;
UINT uiSom;
void WriteByte(BYTE b) { m_pbuf[m_len++] = b; }
void Init()
{
Prob = (1 << 10);
Low = 0;
uiSom = 0xFFFFFFFF;
_cacheSize = 0;
_cache = 0;
}
void ShiftLow()
{
此處空13行代碼;
}
public:
void SetOutputBufPtr(PBYTE buf)
{
Init();
m_pbuf = buf;
m_len = 0;
}
int GetLength() { return m_len; }
void FlushData()
{
此處空2行代碼;
}
void bEncode(UINT symbol)
{
此處空17行代碼;
}
};
//---------------以上是 Encoder 以下是 Decoder
class CBitDecoder
{
PBYTE m_psrc;
int m_srclen;
UINT uiSom;
UINT uiAny;
UINT Prob;
BYTE ReadByte()
{
m_srclen--;
return *m_psrc++;
}
void Init()
{
Prob = (1 << 10);
uiAny = 0;
uiSom = 0xFFFFFFFF;
for(int i = 0; i < 4; i++)
uiAny = (uiAny << 8) | this->ReadByte();
}
public:
void SetSrcBuf(PBYTE psrc, int srclen)
{
m_psrc = psrc;
m_srclen = srclen;
Init();
}
int GetRemainByte() { return m_srclen; }
bool bDecode()
{
bool b;
UINT u = (this->uiSom >> 11) * this->Prob;
if (this->uiAny < u)
{
this->uiSom = u;
this->Prob += ((1 << 11) - this->Prob) >> 5;
b = false;
}
else
{
this->uiSom -= u;
this->uiAny -= u;
this->Prob -= (this->Prob) >> 5;
b = true;
}
if (this->uiSom < (1 << 24))
{
this->uiAny = (this->uiAny << 8) | this->ReadByte();
this->uiSom <<= 8;
}
return b;
}
};
int Test_Encode(PBYTE psrc, int srclen, PBYTE buf)
{
CBitEncoder bitEncoder;
bitEncoder.SetOutputBufPtr(buf);
for (int i=0;i<srclen;i++)
{
BYTE b = psrc[i];
for (int j=0;j<8;j++)
{
bitEncoder.bEncode((b>>j) & 1);
}
}
bitEncoder.FlushData();
return bitEncoder.GetLength();
}
int Test_Decode(PBYTE psrc, int srclen, PBYTE buf)
{
CBitDecoder bitDecoder;
bitDecoder.SetSrcBuf(psrc, srclen);
int totallen = 0;
for (;;)
{
BYTE b = 0;
for (int i=0;i<8;i++)
{
b += (bitDecoder.bDecode() << i);
if (bitDecoder.GetRemainByte() < 0)
return totallen;
}
*buf++ = b;
totallen++;
}
return totallen;
}
void main()
{
char* psrc = "exam by LiuTaoTao 20070728";
int srclen = strlen(psrc);
BYTE buf[3000];
int len = Test_Encode((PBYTE)psrc, srclen, buf);
printf("Srclen = %d Encode len = %d /n", srclen, len);
BYTE outbuf[3000];
int len2 = Test_Decode(buf, len, outbuf);
printf("Decode len from %d to %d /n", len, len2);
if (len2 >= srclen && !memcmp(psrc, outbuf, srclen))
printf("OK/n");
else
printf("Error/n");
}
// 這種壓縮演算法,代碼簡單,速度快
// 還有一個缺點,就是不能很有效地判斷是否已經解碼結束,有時候會多解幾個位元組出來