110204 Crypt Kicker

来源:互联网 发布:单片机定时器初值计算 编辑:程序博客网 时间:2024/05/01 12:05


#include <stdio.h>#include <iostream>#include <string>#include <map>#include <vector>#include <string.h>using namespace std;#define MAX_WORD_LEN 16#define MAX_BUF_SIZE 4096typedef vector<string*> DictStrCol_t;typedef vector<char*> LineStrCol_t;typedef map<char, char> RulesSet_t;class Dict{public:~Dict(){for (int i = 1; i <= MAX_WORD_LEN; ++i){ClearStrCol(m_Words[i]);}}void AddStr(char* str){m_Words[strlen(str)].push_back(new string(str));}const DictStrCol_t* GetCandidateDictStrs(int nLen) const{if ((nLen < 1) || (nLen > MAX_WORD_LEN))return NULL;return &(m_Words[nLen]);}private:static void ClearStrCol(DictStrCol_t& strCol){DictStrCol_t::iterator strIter = strCol.begin();for(int j = 0; j < strCol.size(); ++j)delete (*(strIter + j));strCol.clear();}private:DictStrCol_t m_Words[MAX_WORD_LEN + 1];};enum AddRuleResult_t{CAN_ADD = 0,CONFLICT_WITH_EXIST,EXISTED};enum ParseResult_t{SUCCESS = 0,FAIL,ABORT};class MapRules{public:MapRules(){for (char x = 'a'; x <= 'z'; ++x){m_Rules[x - 'a'] = '*';m_InvertRules[x - 'a'] = '*';}}char GetDecryptedChar(char encryptedChar) const{return m_Rules[encryptedChar - 'a'];}void AddRules(const RulesSet_t* pNewRules){if (!pNewRules)return;RulesSet_t::const_iterator iter = pNewRules->begin();while(iter != pNewRules->end()){m_Rules[iter->first - 'a'] = iter->second;m_InvertRules[iter->second - 'a'] = iter->first;++iter;}}void RemoveRules(const RulesSet_t* pToDeleteRules){if (!pToDeleteRules)return;RulesSet_t::const_iterator iter = pToDeleteRules->begin();while(iter != pToDeleteRules->end()){char curValue = m_Rules[iter->first - 'a'];m_Rules[iter->first - 'a'] = '*';m_InvertRules[curValue - 'a'] = '*';++iter;}}AddRuleResult_t CanAddRule(char encryptedChar, char decryptedChar) const{char curValue = m_Rules[encryptedChar - 'a'];char curInvertValue = m_InvertRules[decryptedChar - 'a'];if (('*' == curValue) && ('*' == curInvertValue))return CAN_ADD;if ((curValue == decryptedChar) && (curInvertValue == encryptedChar))return EXISTED;return CONFLICT_WITH_EXIST;}private:char m_Rules[26];char m_InvertRules[26]; // Help to make sure that no two letters can be mapped to a same letter.};class CandidateRules{public:enum RulesInitResult_t{INIT_OK = 0,NONE_IN_DICT,INIT_FAIL};~CandidateRules(){int nCnt = GetCnt();for (int i = 0; i < nCnt; ++i){delete m_Rules[i];delete m_InvertRules[i];}}RulesInitResult_t Init(const Dict& dict, const MapRules& existingRules, char* str){int nLen = strlen(str);const DictStrCol_t* dictWords = dict.GetCandidateDictStrs(nLen);if ((!dictWords) || (dictWords->size() <= 0))return NONE_IN_DICT;bool isSuccessful;RulesSet_t *newRules, *invertRules;for (int i = 0; i < dictWords->size(); ++i){if (GetNewRules((*(dictWords->begin() + i))->c_str(), str, nLen, existingRules, &newRules, &invertRules)){m_Rules.push_back(newRules);m_InvertRules.push_back(invertRules);}}return (m_Rules.size() > 0) ? INIT_OK : INIT_FAIL;}int GetCnt(){return m_Rules.size();}RulesSet_t* GetRule(int nIndex){return m_Rules[nIndex];}private:AddRuleResult_t CanAddRule(char dictLetter, char strLetter, const MapRules& existingRules, RulesSet_t* newRules, RulesSet_t* invertRules){AddRuleResult_t result = existingRules.CanAddRule(strLetter, dictLetter);if ((CONFLICT_WITH_EXIST == result) || (EXISTED == result))return result;int existingEncrptedLetterCnt = newRules->count(strLetter);int existingDecrptedLetterCnt = invertRules->count(dictLetter);if ((existingEncrptedLetterCnt <= 0) && (existingDecrptedLetterCnt <= 0))return CAN_ADD;if ((existingEncrptedLetterCnt == 1) && (existingDecrptedLetterCnt == 1)){if ((newRules->operator[](strLetter) == dictLetter) &&(invertRules->operator[](dictLetter) == strLetter))return EXISTED;}return CONFLICT_WITH_EXIST;}bool GetNewRules(const char* dictWord, char* str, int nLen, const MapRules& existingRules, RulesSet_t** pNewRules, RulesSet_t** pInvertRules){*pNewRules = new RulesSet_t();*pInvertRules = new RulesSet_t();for(int i = 0; i < nLen; ++i){AddRuleResult_t result = CanAddRule(dictWord[i], str[i], existingRules, *pNewRules, *pInvertRules);if (CONFLICT_WITH_EXIST == result){delete (*pNewRules);*pNewRules = NULL;delete (*pInvertRules);*pInvertRules = NULL;return false;}if (CAN_ADD == result){(*pNewRules)->insert(pair<char, char>(str[i], dictWord[i]));(*pInvertRules)->insert(pair<char, char>(dictWord[i], str[i]));}}return true;}private:vector<RulesSet_t*> m_Rules;vector<RulesSet_t*> m_InvertRules; // Help to make sure that no two letters can be mapped to a same letter.};void GetWordsFromLine(char* pLine, LineStrCol_t& strCol){int start = 0;int nIndex = 0;while(pLine[nIndex] != '\0'){if ((pLine[nIndex] == ' ') || (pLine[nIndex] == '\n')){pLine[nIndex] = '\0';strCol.push_back(pLine + start);++nIndex;start = nIndex;continue;}++nIndex;}}void OutputDecryptedLine(LineStrCol_t& lineStrCol, MapRules& rules){int nWordsCnt = lineStrCol.size();for (int i = 0; i < nWordsCnt; ++i){char* ptr = lineStrCol[i];while((*ptr) != '\0'){*ptr = rules.GetDecryptedChar(*ptr);++ptr;}cout << lineStrCol[i];if (i < nWordsCnt - 1)cout << ' ';elsecout << endl;}}ParseResult_t GetRules(Dict& dict, const LineStrCol_t& encrptedWords, int curIndex, MapRules& rules){if (curIndex >= encrptedWords.size())return SUCCESS;CandidateRules candidateNewRules;CandidateRules::RulesInitResult_t initResult = candidateNewRules.Init(dict, rules, encrptedWords[curIndex]);if (CandidateRules::NONE_IN_DICT == initResult)return ABORT;if (CandidateRules::INIT_OK != initResult)return FAIL;int nCnt = candidateNewRules.GetCnt();if (nCnt <= 0)return FAIL;for(int i = 0; i < nCnt; ++i){RulesSet_t* newRules = candidateNewRules.GetRule(i);rules.AddRules(newRules);ParseResult_t result = GetRules(dict, encrptedWords, curIndex+1, rules);if (SUCCESS == result)return SUCCESS;rules.RemoveRules(newRules);if (ABORT == result)return ABORT;}return FAIL;}void DecryptLine(Dict& dict, char* pLine){int nLen = strlen(pLine);LineStrCol_t encryptedWords;GetWordsFromLine(pLine, encryptedWords);MapRules rules;GetRules(dict, encryptedWords, 0, rules);OutputDecryptedLine(encryptedWords, rules);}void DoWork(Dict& dict){int nDictWordsCnt = 0;cin >> nDictWordsCnt;char buf[MAX_BUF_SIZE];for(int i = 0; i < nDictWordsCnt; ++i){cin >> buf;dict.AddStr(buf);}fgets(buf, MAX_BUF_SIZE, stdin); // Consume the "\n" after the last word in dictionary.while(true){char* ptr = fgets(buf, MAX_BUF_SIZE, stdin);if (!ptr)return;if (buf[0] == '\n'){cout << endl;continue;}DecryptLine(dict, buf);}}int main(int argc, char* argv[]){Dict dict;DoWork(dict);return 0;}