您的位置:首页 > 其它

Cryptcowgraphy [USACO]

2013-03-14 11:34 357 查看
擦,公司上不了USACO了,怀疑公司用了一个牛X的防火墙,通过机器学习把我给禁掉了,实在恶心。我还以为USACO挂掉了,还好今天灵机一动,用“在线代理”这个有点sexy的网站可以突破天际。  

这道题太恶心。。。我开始用的set<string> 妥妥的,bad_alloc啥的,可能是内存不足吧(USACO有16M内存的限制??),后来自己实现了个hash表,自己来,擦的,用了16228KB,又bad_alloc了,折腾许久,无解。百度了一下,发现大家都不解决hash conflict,居然也过了...唉,就这样吧,我用的BKDR_Hash,因为这个hash 简单,而且效果很好,有本书上讲的。

/*
ID: zhangyc1
LANG: C++
TASK: cryptcow
*/
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;

// Begin the Escape execution at the Break of Dawn

ofstream fileout("cryptcow.out");
string strNormal = "Begin the Escape execution at the Break of Dawn";
string strInput;
int strInputLen = 0;
int arrChNum[2][53];

bool bEable = false;
int nRs = 0;
const int HashSize = 362881;
/*
struct SHash
{
char* str;
SHash* pNext;
SHash():str(NULL), pNext(NULL){}
};
*/

//SHash* hashTable[HashSize];
bool hashTable[HashSize];

unsigned int BKDR_Hash(const string& ss)
{
unsigned int nSeed = 131;
unsigned int nHash = 0;
int nLen = ss.length();
for (int i = 0; i < nLen; i++)
nHash = nHash * nSeed + (unsigned int)ss[i];
return nHash % HashSize;
}

bool prepairData()
{
memset(arrChNum, 0, sizeof(arrChNum));
memset(hashTable, 0, sizeof(hashTable));
ifstream filein("cryptcow.in");
getline(filein, strInput);
filein.close();
strInputLen = strInput.size();
int nNumC = 0, nNumO = 0, nNumW = 0, nNumSp = 0;
int arrPosC[9], arrPosO[9], arrPosW[9], arrPosSp[30];
for (int i = 0; i < strInputLen; i++)
{
if (strInput[i] == 'C')
{
arrPosC[nNumC++] = i;
}
else if (strInput[i] == 'O')
{
arrPosC[nNumO++] = i;
}
else if (strInput[i] == 'W')
{
arrPosW[nNumW++] = i;
}
else
{
if (strInput[i] >= 'A' && strInput[i] <= 'Z')
arrChNum[1][strInput[i] - 'A']++;
else if (strInput[i] >= 'a' && strInput[i] <= 'z')
arrChNum[1][strInput[i] - 'a' + 26]++;
else
arrChNum[1][52]++;
}
if (nNumC > 9 || nNumO > 9 || nNumW > 9)
{
return false;
}
}
// C O W 个数相等
if (nNumC != nNumO || nNumO != nNumW)
return false;

for (int i = 0; i < 47; i++)
{
if (strNormal[i] >= 'A' && strNormal[i] <= 'Z')
arrChNum[0][strNormal[i] - 'A']++;
else if(strNormal[i] >= 'a' && strNormal[i] <= 'z')
arrChNum[0][strNormal[i] - 'a' + 26]++;
else
arrChNum[0][52]++;
}
// 各字符个数相等
for (int i = 0; i < 53; i++)
{
if (arrChNum[0][i] != arrChNum[1][i])
return false;
}

nRs = nNumC;
return true;
}

bool dfs(string ss)
{
int nNumC = 0, nNumO = 0, nNumW = 0, nNumSp = 0;
int arrPosC[9], arrPosO[9], arrPosW[9], arrPosSp[30];
int nStrLen = ss.length();
if (nStrLen == 47)
return ss.compare(strNormal) == 0;

for (int i = 0; i < nStrLen; i++)
{
if (ss[i] == 'C')
{
arrPosC[nNumC++] = i;
arrPosSp[nNumSp++] = i;
}
else if (ss[i] == 'O')
{
arrPosO[nNumO++] = i;
arrPosSp[nNumSp++] = i;
}
else if (ss[i] == 'W')
{
arrPosW[nNumW++] = i;
arrPosSp[nNumSp++] = i;
}
}

if (arrPosSp[0] != arrPosC[0] || arrPosSp[nNumSp - 1] != arrPosW[nNumW - 1])
return false;

string strSub = "";
if (arrPosSp[0] != 0)
{
strSub = ss.substr(0, arrPosSp[0]);
// 必须为目标串的开头
if (strSub.compare(strNormal.substr(0, arrPosSp[0])) != 0)
return false;
}
if (arrPosSp[nNumSp - 1] != nStrLen - 1)
{
strSub = ss.substr(arrPosSp[nNumSp - 1] + 1, nStrLen - arrPosSp[nNumSp - 1] - 1);
// 必须为目标串的结尾
if (strSub.compare(strNormal.substr(47 - nStrLen + arrPosSp[nNumSp - 1] + 1, nStrLen - arrPosSp[nNumSp - 1] - 1)) != 0)
return false;
}

for (int i = 0; i <= nNumSp - 2; i++)
{
strSub = ss.substr(arrPosSp[i] + 1, arrPosSp[i + 1] - arrPosSp[i] - 1);
if (strSub.length() == 0)
continue;
else if (strSub.length() == 47)
return strSub.compare(strNormal) == 0;
else
{
unsigned int nHash = BKDR_Hash(strSub);
if (strNormal.find(strSub) == string::npos)
return false;
}
}

for (int i = 0; i < nNumC; i++)
for (int j = 0; j < nNumO; j++)
{
if (arrPosO[j] < arrPosC[i])
continue;
for (int k = nNumW - 1; k >= 0; k--)
{
if (arrPosW[k] < arrPosO[j])
continue;
string s0 = ss.substr(0, arrPosC[i]);
string s1 = ss.substr(arrPosC[i] + 1, arrPosO[j] - arrPosC[i] - 1);
string s2 = ss.substr(arrPosO[j] + 1, arrPosW[k] - arrPosO[j] - 1);
string s3 = ss.substr(arrPosW[k] + 1, nStrLen - arrPosW[k] - 1);
string newSS = s0 + s2 + s1 + s3;
bool bSkip = false;
for (int i = 0; i < newSS.length(); i++)
{
if (newSS[i] == 'C')
break;
else if (newSS[i] == 'O' || newSS[i] == 'W')
{
bSkip = true;
break;
}
}
if (bSkip)
continue;
for (int i = newSS.length() - 1; i >= 0; i--)
{
if (newSS[i] == 'W')
break;
else if (newSS[i] == 'O' || newSS[i] == 'C')
{
bSkip = true;
break;
}
}
if (bSkip)
continue;

unsigned int nHash = BKDR_Hash(newSS);
/*
SHash* pHash = hashTable[nHash];
SHash* pPreHash = NULL;
while (pHash && pHash->str)
{
if (strcmp(pHash->str, newSS.c_str()) == 0)
{
bSkip = true;
break;
}
pPreHash = pHash;
pHash = pHash->pNext;
}
if (bSkip)
continue;
*/
if (!hashTable[nHash])
{
if (dfs(newSS))
return true;
else
hashTable[nHash] = true;
}
/*
if (dfs(newSS))
return true;

pHash = new SHash();
pHash->str = new char[newSS.length() + 1];
strcpy(pHash->str, newSS.c_str());
if (pPreHash)
pPreHash->pNext = pHash;
*/
}
}
return false;
}

void process()
{
bEable = dfs(strInput);
if (!bEable)
nRs = 0;
}

int main(){
if(prepairData())
{
process();
}
fileout << bEable << " " << nRs << endl;
fileout.close();
return 0;
}


原题如下:

Cryptcowgraphy
Brian Dean
The cows of Farmer Brown and Farmer John are planning a coordinated escape from their respective farms and have devised a method of encryption to protect their written communications.

Specifically, if one cow has a message, say, "International Olympiad in Informatics", it is altered by inserting the letters C, O, and W, in random location in the message, such that C appears before O, which appears before W. Then the cows take the part of the message between C and O, and the part between O and W, and swap them. Here are two examples:

International Olympiad in Informatics
->
CnOIWternational Olympiad in Informatics

International Olympiad in Informatics
->
International Cin InformaticsOOlympiad W

To make matters more difficult, the cows can apply their encryption scheme several times, by again encrypting the string that results from the previous encryption. One night, Farmer John's cows receive such a multiply-encrypted message. Write a program to compute whether or not the non-encrypted original message could have been the string:

Begin the Escape execution at the Break of Dawn

PROGRAM NAME: cryptcow

INPUT FORMAT

A single line (with both upper and lower case) with no more than 75 characters that represents the encrypted message.

SAMPLE INPUT (file cryptcow.in)

Begin the EscCution at the BreOape execWak of Dawn

OUTPUT FORMAT

Two integers on a single line. The first integer is 1 if the message decodes as an escape message; 0 otherwise. The second integer specifies the number of encryptions that were applied (or 0 if the first integer was 0).

SAMPLE OUTPUT (file cryptcow.out)

1 1

----------------------------------------------------------------------------------分割线---------------------------------------------------------------

以下为测试数据:

Here are the test data inputs:

------- test 1 ----
Begin the Escape execution at the Break of Dawn
------- test 2 ----
CBegin the EscCution at the BreOape execWak of OWDawn
------- test 3 ----
Begin the EscCutino at the BreOape execWak of Dawn
------- test 4 ----
Begin the EscCCCCCCution at the BreOOOOOOape execWWWWWWak of Dawn
------- test 5 ----
CaOBegin the EscWpe CnCak OexeOt the BWcutioWofO aCreW Dawn
------- test 6 ----
BCC execuO the EsCinCaWCCreaOpWtiOn at OCDOcOWaOegCeWtheOW BWoWk of Wwn
------- test 7 ----
BegiCoWCWDOk oCthe EscOWaCn Oe Of On WexecutChe BreOOCat tWiWapCWawn
------- test 8 ----
BeCOgC CC execuOf DOBCiCCrWaOOt theCOCeak oWWin Oon aWtheOOW EscapeWtWWWwn
------- test 9 ----
CChCC Oe BWOWEscapCreOeOegin tWOe WatWaOe OBCexCOhWC of O tCWcutionWkWDawn
------- test 10 ----
CCC COhe BWOWEscapCreOeOegin tWOe WatWaOe OBCexCOhWC of O tCWcutionWkWDawn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: