110306 File Fragmentation


#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <map>
#include <set>
using namespace std;

#define MAX_CHAR_IN_LINE (256 + 2)

static char s_buf[MAX_CHAR_IN_LINE];

class Fragments
{
private:
	typedef map<int, vector<string*>*>::iterator MapIter;
	struct FragmentsPair 
	{
		FragmentsPair(vector<string*>* shorterStrs, vector<string*>* longerStrs,
			int shorterLen, int longerLen) : 
			m_shorterStrs(shorterStrs), m_longerStrs(longerStrs),
			m_shorterlen(shorterLen), m_longerLen(longerLen)
		{
		}

		int m_shorterlen;
		int m_longerLen;

		vector<string*>* m_shorterStrs;
		vector<string*>* m_longerStrs;
	};

public:
	~Fragments()
	{
		MapIter mapIter = m_fragments.begin();
		while (mapIter != m_fragments.end())
		{
			if (mapIter->second)
			{
				vector<string*>::iterator vecIter = mapIter->second->begin();
				while (vecIter != mapIter->second->end())
				{
					delete (*vecIter);
					++vecIter;
				}
				delete mapIter->second;
			}
			++mapIter;
		}
	}

	void AddFragment(char* line, int len)
	{
		MapIter iter = m_fragments.find(len);
		if (iter == m_fragments.end())
		{
			m_fragments.insert(pair<int, vector<string*>*>(len, new vector<string*>));
			iter = m_fragments.find(len);
		}

		iter->second->push_back(new string(line));
	}

	void OutputOriginalFile()
	{
		string originalFile;
		Reorganize(originalFile);
		cout << originalFile.c_str() << endl;
	}

private:
	void Preparation(int& targetLen, int& totalCnt, size_t& minSameLenFragmentsCnt)
	{
		MapIter iter = m_fragments.begin();
		int totalLen = 0;
		totalCnt = 0;
		minSameLenFragmentsCnt = iter->second->size();

		while (iter != m_fragments.end())
		{
			size_t vecSize = iter->second->size();
			totalLen += (iter->first) * vecSize;
			totalCnt += vecSize;
			if (vecSize < minSameLenFragmentsCnt)
				minSameLenFragmentsCnt = vecSize;

			++iter;
		}

		targetLen = (totalLen * 2) / totalCnt;
	}

	void GetFragmentsPairs(int targetLen, int totalCnt, size_t minSameLenFragmentsCnt, 
		vector<FragmentsPair>& fragmentsPairs, int& startPointIndex)
	{
		MapIter iter = m_fragments.begin();
		bool even = ((targetLen % 2) == 0);
		int halfLen = targetLen / 2;
		startPointIndex = 0;

		while (iter != m_fragments.end())
		{
			if (iter->first <= halfLen)
			{
				vector<string*>* longerStrs = NULL;
				if ((!even) || (iter->first < halfLen))
					longerStrs = m_fragments.find(targetLen - iter->first)->second;
				fragmentsPairs.push_back(FragmentsPair(iter->second, longerStrs, iter->first, targetLen - iter->first));
				if (iter->second->size() == minSameLenFragmentsCnt)
					startPointIndex = fragmentsPairs.size() - 1;
			}

			++iter;
		}
	}

	bool StrStartsWith(const string& refStr, const string& subStr)
	{
		int i = 0;
		while(subStr[i] != 0)
		{
			if (refStr[i] != subStr[i])
				return false;
			++i;
		}
		return true;
	}

	bool StrEndsWith(const string& refStr, int startIndex, const string& subStr)
	{
		int i = 0;
		while(subStr[i] != 0)
		{
			if (refStr[startIndex + i] != subStr[i])
				return false;
			++i;
		}
		return true;
	}

	bool CanFindMatch(const string& refStr, const FragmentsPair& fragmentsPair)
	{
		size_t cnt = fragmentsPair.m_shorterStrs->size();

		vector<string*>* longerParts;
		size_t shorterPartsEndIndex, longerPartsStartIndex;
		if (fragmentsPair.m_longerStrs)
		{
			longerParts = fragmentsPair.m_longerStrs;
			shorterPartsEndIndex = cnt;
			longerPartsStartIndex = 0;
		}
		else
		{
			longerParts = fragmentsPair.m_shorterStrs;
			shorterPartsEndIndex = cnt/2;
			longerPartsStartIndex = cnt/2;
		}

		set<int> handledLonger;

		for (size_t i = 0; i < shorterPartsEndIndex; ++i)
		{
			string* shorterStr = (*fragmentsPair.m_shorterStrs)[i];
			bool found = false;
			for (size_t j = longerPartsStartIndex; j < cnt; ++j)
			{
				if (handledLonger.find(j) != handledLonger.end())
					continue;

				string* longerStr = (*longerParts)[j];
				if (StrStartsWith(refStr, *shorterStr))
				{
					if (StrEndsWith(refStr, fragmentsPair.m_shorterlen, *longerStr))
					{
						handledLonger.insert(j);
						found = true;
						break;
					}
				}
				else if (StrStartsWith(refStr, *longerStr))
				{
					if (StrEndsWith(refStr, fragmentsPair.m_longerLen, *shorterStr))
					{
						handledLonger.insert(j);
						found = true;
						break;
					}
				}
			}
			if (!found)
				return false;
		}

		return true;
	}

	bool CanBeOriginalFile(const string& refStr, const vector<FragmentsPair>& fragmentsPairs, int startPointIndex)
	{
		size_t totalPairs = fragmentsPairs.size();

		for (size_t j = 0; j < totalPairs; ++j)
		{
			if (j == startPointIndex)
				continue;

			if (!CanFindMatch(refStr, fragmentsPairs[j]))
				return false;
		}

		return true;
	}

	bool CanPairOfStrsBeOriginalFile(const string& shorterStr, const string& longerStr, 
		const vector<FragmentsPair>& fragmentsPairs, int startPointIndex, string& mergedStr)
	{
		mergedStr = shorterStr;
		mergedStr.append(longerStr);

		if (CanBeOriginalFile(mergedStr, fragmentsPairs, startPointIndex))
			return true;

		mergedStr = longerStr;
		mergedStr.append(shorterStr);

		return CanBeOriginalFile(mergedStr, fragmentsPairs, startPointIndex);		
	}

	void Repair(const vector<FragmentsPair>& fragmentsPairs, int startPointIndex, string& originalFile)
	{
		const FragmentsPair& startPointPair = fragmentsPairs[startPointIndex];

		size_t cnt = startPointPair.m_shorterStrs->size();

		vector<string*>* longerParts;
		size_t shorterPartsEndIndex, longerPartsStartIndex;
		if (startPointPair.m_longerStrs)
		{
			longerParts = startPointPair.m_longerStrs;
			shorterPartsEndIndex = cnt;
			longerPartsStartIndex = 0;
		}
		else
		{
			longerParts = startPointPair.m_shorterStrs;
			shorterPartsEndIndex = cnt/2;
			longerPartsStartIndex = cnt/2;
		}

		for (size_t i = 0; i < shorterPartsEndIndex; ++i)
		{
			string* shorterStr = (*startPointPair.m_shorterStrs)[i];
			for (size_t j = longerPartsStartIndex; j < cnt; ++j)
			{
				string mergedStr;
				if (CanPairOfStrsBeOriginalFile(*shorterStr,
					*((*longerParts)[j]),
					fragmentsPairs, startPointIndex, mergedStr))
				{
					originalFile = mergedStr;
					return;
				}
			}
		}
	}

	void Reorganize(string& originalFile)
	{
		int targetLen, totalCnt;
		size_t minSameLenFragmentsCnt;
		Preparation(targetLen, totalCnt, minSameLenFragmentsCnt);

		vector<FragmentsPair> fragmentsPairs;
		int startPointIndex;
		GetFragmentsPairs(targetLen, totalCnt, minSameLenFragmentsCnt, fragmentsPairs, startPointIndex);

		Repair(fragmentsPairs, startPointIndex, originalFile);
	}

private:
	map<int, vector<string*>*> m_fragments;
};

static void RunTestCase()
{
	Fragments fragments;
	while(true)
	{
		if (!fgets(s_buf, MAX_CHAR_IN_LINE, stdin))
			break;
		if ((s_buf[0] == '\0') || (s_buf[0] == '\n'))
			break;
		int len = strlen(s_buf);
		if (s_buf[len - 1] == '\n')
		{
			s_buf[len - 1] = '\0';
			len -= 1;
		}
		fragments.AddFragment(s_buf, len);
	}
	fragments.OutputOriginalFile();
}

static void RunTests()
{
	int testCaseCnt;
	cin >> testCaseCnt;

	fgets(s_buf, MAX_CHAR_IN_LINE, stdin); // Consume the '\n' right after the test case count.
	fgets(s_buf, MAX_CHAR_IN_LINE, stdin); // Consume the empty line after the test case count.

	for (int i = 0; i < testCaseCnt; ++i)
	{
		RunTestCase();
		if (i < (testCaseCnt - 1))
			cout << endl;
	}
}

int main(int argc, char* argv[])
{
	RunTests();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值