Public Class FileFragments
Function GetOriginalFile(ByVal fragments As List(Of String)) As String
Dim frags As New List(Of String)(fragments)
frags.Sort(AddressOf CompareLength)
Dim candidate As List(Of String) = GetCombined(frags(0), frags)
RemoveDuplicated(candidate)
For i As Integer = 1 To frags.Count - 1
If candidate.Count = 1 Then Exit For
Dim combined As List(Of String) = GetCombined(frags(i), frags)
RemoveWrongCandidate(candidate, combined)
Next
Return candidate(0)
End Function
Private Sub RemoveDuplicated(ByVal candidate As List(Of String))
Dim i As Integer
While i < candidate.Count
Dim duplicated As Integer = candidate.IndexOf(candidate(i), i + 1)
If duplicated <> -1 Then
candidate.RemoveAt(i)
Else
i += 1
End If
End While
End Sub
Private Sub RemoveWrongCandidate(ByVal candidate As List(Of String), ByVal combined As List(Of String))
Dim i As Integer
While i < candidate.Count
If combined.IndexOf(candidate(i)) = -1 Then
candidate.RemoveAt(i)
Else
i += 1
End If
End While
End Sub
Private Function GetCombined(ByVal frag, ByVal frags) As List(Of String)
Dim originalLength As Integer = frags(0).Length + frags(frags.Count - 1).Length
Dim combined As New List(Of String)
For i As Integer = frags.Count - 1 To 0 Step -1
Dim compared As String = frags(i)
If compared.Length + frag.Length = originalLength Then
combined.Add(frag + compared)
combined.Add(compared + frag)
End If
Next
Return combined
End Function
Private Shared Function CompareLength(ByVal str1 As String, ByVal str2 As String) As Integer
If str1.Length > str2.Length Then
Return 1
ElseIf str1.Length < str2.Length Then
Return -1
Else
Return 0
End If
End Function
End Class
// "File Fragmentation" Solution By Outbreak
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
//#define _TDD
// ํ ํ์ผ์ ํฌ๊ธฐ ๊ตฌํ ์ ์์.
// ๊ฐ ์กฐ๊ฐ์ ์๋ถ๋ถ ์๋๋ฉด ๋ท๋ถ๋ถ!
// ํด๋์ค๋ก ๋ฆฌํฉํ ๋ง ํ ๊ฒ!
namespace Solver
{
static const int MAX_FRAGMENT = 144 * 2;
static vector<string> VFragment(MAX_FRAGMENT);
void MakeFragmentTable()
{
VFragment.clear();
}
void InsertFragment(const string& fragment)
{
VFragment.push_back(fragment);
}
int FindCompleteFileLength()
{
int sum = 0;
int n = (int)VFragment.size() / 2;
if(n==0)
return -1;
for( int i=0; i<(int)VFragment.size(); i++ )
{
sum += (int)VFragment[i].length();
}
return sum / n;
}
bool CheckCompleteFile(string front, string end)
{
string file = front + end;
// ๊ฒ์ฆ
// ๋ชจ๋ ์กฐ๊ฐ๋ค์ด ๋ง์ถฐ์ง๋์ง ํ์ธํด ๋ณธ๋ค.
int i;
// ์, ๋ค์์ ์ฐพ์๋ด.
for( i=0; i<(int)VFragment.size(); i++ )
{
size_t pos = file.find(VFragment[i]);
// ์
if( pos == 0 )
continue;
// ๋ค
pos = file.rfind(VFragment[i]);
if( pos + VFragment[i].length() == file.length() )
continue;
return false;
}
return true;
}
string Recovery()
{
string result = "01110111";
// ํ์ผ์ ํฌ๊ธฐ๋ฅผ ์ฐพ๋๋ค.
int length = FindCompleteFileLength();
if( length == -1 )
return "error";
const int remain = length - (int)VFragment[0].length();
set<string> Set;
// ์ฒซ๋ฒ์งธ ์กฐ๊ฐ์ ์์ด๋ผ๊ณ ๊ฐ์
// ์ง์ด ๋ ์ ์๋ ๋
์๋ค ์กฐ์ฌ. set ์๋ค ๋ฃ๋๋ค.
for( int i=0; i<(int)VFragment.size(); i++ )
{
if( remain == (int)VFragment[i].length() )
{
Set.insert(VFragment[i]);
}
}
// ์์ผ ๊ฒฝ์ฐ Set ์ ๋ ๋
์๋ค ํฉํด์ ๋ฌธ์ฅ ๋ง๋ค๊ธฐ
for( set<string>::iterator it = Set.begin(); it != Set.end(); it++ )
{
if( CheckCompleteFile(VFragment[0],*it) )
{
result = VFragment[0] + *it;
return result;
}
}
// ๋ค์ผ ๊ฒฝ์ฐ Set ์ ๋ ๋
์๋ค ํฉํด์ ๋ฌธ์ฅ ๋ง๋ค๊ธฐ
for( set<string>::iterator it = Set.begin(); it != Set.end(); it++ )
{
if( CheckCompleteFile(*it, VFragment[0]) )
{
result = *it + VFragment[0];
return result;
}
}
return "none";
}
}
namespace Runner
{
void Execute(istream& in, ostream& out)
{
int sample = 0;
in >> sample;
while( sample-- )
{
// ํ
์ด๋ธ ์ด๊ธฐํ
Solver::MakeFragmentTable();
while(true)
{
string fragment;
in >> fragment;
if( in.fail() )
break;
// ์กฐ๊ฐ ๋ฃ๊ธฐ
Solver::InsertFragment(fragment);
in.get();
if( in.peek() == '\n')
{
break;
}
}
// ์ฒ๋ฆฌ ํ๊ธฐ
out << Solver::Recovery() << endl;
if( sample > 0 )
{
out << endl;
}
}
}
}
#ifdef _TDD
#include "unittest++.h"
TEST(Output)
{
stringstream input;
stringstream output;
input <<
"2\n\n"
"011\n"
"0111\n"
"01110\n"
"111\n"
"0111\n"
"10111\n"
"\n"
"011\n"
"0111\n"
"01110\n"
"111\n"
"0111\n"
"10111";
Runner::Execute(input, output);
CHECK_EQUAL("01110111\n01110111",output.str());
}
#endif
int main()
{
#ifdef _TDD
UnitTest::RunAllTests();
#else
Runner::Execute(cin, cout);
#endif // _TDD
return 0;
}