algorithm edit step ladder - andstudy/forge GitHub Wiki
- ๋จ์ด์ ํ ๋ฌธ์๋ฅผ ์ถ๊ฐ, ์ญ์ , ๋ณ๊ฒฝํ ๋ค๋ฅธ ๋จ์ด๊ฐ ์ฌ์ ์ ์๋ ๊ฒฝ์ฐ ๋จ๋ฐฉํฅ ์์ง ์์ฑ
- ๋จ๋ฐฉํฅ ์์ง๋ฅผ ๋ฐ๋ผ ์ต๋ ์ด๋ ๊ฐ๋ฅํ ๋จ์ด์ ๊ฐ์๋?
- ๋งต์ ์ด์ฉํด ๋จ์ด Pool ์์ฑ.
- ํ ๋ฌธ์๋ฅผ ์ถ๊ฐ, ์ญ์ , ๋ณ๊ฒฝ ํ๋ EditStep ์ ์คํํ์ ๋ ๋จ์ด๊ฐ Pool ์ ์์ผ๋ฉด ์์ง ์์ฑ
- EditStep ์ด ๊ฐ๋ฅํ ๋จ์ด๋ค๋ผ๋ฆฌ ์์ง ๊ด๊ณ ํ ์ด๋ธ ์์ฑ(๋ฉ๋ชจ๋ฆฌ ์ ์ฝ์ ์ํด ๋งต์ฌ์ฉ)
- ๋จ์ด ๊ด๊ณ ํ ์ด๋ธ์ DFS!
- ๋ด์ผ ์ด ์ฝ๋๋ ์์๊ฒ ๋ง๋ค์ด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค~
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
namespace ACM_EditStepLadders
{
class Program
{
public static string[] input =
{
"cat",
"dig",
"dog",
"fig",
"fin",
"fine",
"fog",
"log",
"wine"
};
static Dictionary<string, List<string>> rDic = new Dictionary<string, List<string>>();
static int ๋ต = 0;
static void Dfs(string src, int depth)
{
if (!rDic.ContainsKey(src))
{
if (๋ต < depth)
๋ต = depth;
return;
}
foreach (string s in rDic[src])
{
Dfs(s, depth + 1);
}
}
static void Main(string[] args)
{
// 1. > word pool ๋ง๋ค๊ธฐ
Dictionary<string, int> wDic = new Dictionary<string, int>();
List<string> wList = new List<string>();
Dictionary<int, List<string>> lenDic = new Dictionary<int, List<string>>();
for (int i = 0; i < input.GetLength(0); i++)
{
wList.Add(input[i]);
wDic[input[i]] = i;
if (!lenDic.ContainsKey(input[i].Length))
{
lenDic[input[i].Length] = new List<string>();
}
lenDic[input[i].Length].Add(input[i]);
}
// 2.1 > ๋จ์ด๊ฐ ๊ด๊ณ ๋ง๋ค๊ธฐ
foreach (string src in wList)
{
// ๊ณ ์นจ
for (int i = 0; i < src.Length; i++)
{
char[] tmp = src.ToCharArray();
char init = tmp[i];
init++;
for (char c = init; c <= 'z'; c++)
{
tmp[i] = c;
string key = new string(tmp);
if (string.Compare(key, src, StringComparison.Ordinal) > 1)
{
if (wDic.ContainsKey(key))
{
if (!rDic.ContainsKey(src))
{
rDic[src] = new List<string>();
}
rDic[src].Add(key);
}
}
}
}
}
foreach (string src in wList)
{
// ์ถ๊ฐ
for (int i = 0; i <= src.Length; i++)
{
char[] tmp = src.ToCharArray();
// ๋์ ํ๊ฐ ์ด๋ป๊ฒ ํ๋๋๊ฐ ๋ฌธ์ .
// dog -> do ๊ฐ ๋๋ ์ผ์ด์ค ๋๋ฌธ์ ํท๊ฐ.
char init = 'a';
if (i < src.Length)
{
init = tmp[i];
init++;
}
for (char c = init; c <= 'z'; c++)
{
string key = src.Insert(i, new string(c,1));
if (string.Compare(key, src, StringComparison.Ordinal) > 1)
{
if (wDic.ContainsKey(key))
{
if (!rDic.ContainsKey(src))
{
rDic[src] = new List<string>();
}
rDic[src].Add(key);
}
}
}
}
}
foreach (string src in wList)
{
// ์ญ์
for (int i = 0; i < src.Length; i++)
{
string key = src.Remove(i,1);
if (string.Compare(key, src, StringComparison.Ordinal) > 1)
{
if (wDic.ContainsKey(key))
{
if (!rDic.ContainsKey(src))
{
rDic[src] = new List<string>();
}
rDic[src].Add(key);
}
}
}
}
// 2.2 > ๋จ์ด ๊ด๊ณ ํ์ธ
foreach (KeyValuePair<string, List<string>> p in rDic)
{
Console.Write("{0} - ", p.Key);
foreach (string s in p.Value)
{
Console.Write("{0} ", s);
}
Console.WriteLine();
}
// 3. > DFS
foreach( string s in rDic.Keys )
{
Dfs(s, 1);
break;
}
// 4. > ๋ฌธ์ ํ๊ธฐ
Console.WriteLine("\n์ต๋ ํธ์ง ์ฌ๋ค๋ฆฌ ๋จ์ด ๊ฐ์๋ {0} ์
๋๋ค.\n", ๋ต);
}
}
[TestFixture]
public class Unitest
{
[TestFixtureSetUp]
public void SetUp()
{
}
[TestFixtureTearDown]
public void TearDown()
{
}
}
}
-
์์ ์ ์ถ๋ ฅ๊ฐ์ด 5๊ฐ ๋ง๋์?
- wine -> fine -> fin -> fig -> dig -> dog -> fog -> log
- ์ฌ๋๊ฐ๊ฐ ๋๋ ๊ฒฝ์ฐ๋ ๋์ค๋๋ฐ ๋ฌธ์ ๋ฅผ ์๋ชป ์ดํดํ๊ฐ์? ^^;
- edit step ladder ๋ lexicographically ordered sequence ๋ผ๊ณ ๋์ด ์๋ค์.
- ์ ๊ทธ๋ ๋ค์~! ^^
-
๊ทธ๋ฆฌ๊ณ ์ด์ ์์ผ ๋ฌธ์ ๋ฅผ ์ดํดํ์๋ฉด ์ด๋กํ์๋ ๊ฑด๊ฐ์ค? ์ง๊ธ ์ ๊ฐ ์ ๊ฐ๋ค๊ณ ๊ตฐ๊ธฐ ๋น ์ง ๊ฑด๊ฐ์ค? ๋ฒ๋ญ
- ํํ ๋ฒผ๋ฝ์น๊ธฐ ํ๋๊ฑฐ ์์๋ฉด์.. ^^;
-
dog -> do ์ด๊ฒ ์ฌ์ ์ํ์ค ์์์ ์๋ง๋๊ฑฐ ๊ฐ์์;;
์์ด๋์ด.
- ์ด๋ฏธ ์ฐพ์๋ณธ ๋จ์ด์ ๋ํด์๋ ๋ ์ด์ ์ฐพ์ ํ์๊ฐ ์๋ค.
- ์ฌ์ ์์ผ๋ก ์ฐพ์๋ณด๋ฉด ๋๋ค.
- ๊ฐ์ฅ ๋์ ๊ฐ์ ์ ์งํ๋ค. (DP, ๋ค์ต์คํธ๋ผ)
-
๊ทธ๋ฌ๋ ์ฐ๋ คํ๋๋๋ก Time limit exceeded ๊ฐ ๋๋๊ตฐ์. ์๊ณ ๋ฆฌ์ฆ์ ํ ๊ณ ์ณ์ผ ํ ์ง, ๋ฌธ์์ด ์ชฝ ๋ถ๋ถ์ ์ต์ ํ ํด์ผ ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ฉ...
-
map ์ด๋ set, vector ๋์ array ๋ก ๋ฐ๊ฟ๋ ์ ๋๋ค์. ํ... string ๋ ๋ฐ๊ฟ์ผ ํ ๊น๋...
/* @JUDGE_ID:parkpd 110401 Cpp "test" */ /* @BEGIN_OF_SOURCE_CODE */ #include <iostream> #include <vector> #include <set> #include <string> #include <strstream> #include <algorithm> #include <map> #include <math.h> //#define _UNIT_TEST using namespace std; namespace ATUtil { bool IsInRange(int value, int from, int to) { return (from <= value) && (value <= to); } int ConvertToIndex(char c) { if ('a' <= c && c <= 'z') { return c - 'a'; } else { return -1; } } char ConvertToChar(int i) { return (char)i + 'a'; } typedef map<int, int> IntDB; typedef vector<int> Ints; }; using namespace ATUtil; #ifdef _UNIT_TEST #include "../UnitTest++/src/UnitTest++.h" int main() { UnitTest::RunAllTests(); char temp; cin >> temp; return 0; } #endif // code implement namespace ATCode { string g_Words[25000]; int g_Ladder[25000]; ////////////////////////////////////////////////////////////////////////// // CEditStepLadder class CEditStepLadder { public: CEditStepLadder() : m_Longest(0), m_WordSize(0) {} int m_Longest; int m_WordSize; void Insert(const string& str); void Find(size_t from, const string& word); int GetLongestEditStepLadder(); }; void CEditStepLadder::Insert(const string& str) { g_Words[m_WordSize] = str; g_Ladder[m_WordSize] = 1; m_WordSize++; } void CEditStepLadder::Find(size_t from, const string& word) { int left = (int)from + 1; // ๋๋ณด๋ค ์ฌ์ ์์ผ๋ก ๋์ ๋จ์ด๋ถํฐ ๊ฒ์ ์์ int right = m_WordSize - 1; int mid; while (left <= right) { mid = (left + right) / 2; int cmp = strcmp(g_Words[mid].c_str(), word.c_str()); if (0 == cmp) { // ladder step ์ด ๋ ๊ธด ๊ฒฝ์ฐ์๋ง ์ ๋ฐ์ดํธํ๋ค. int& currentWordStep = g_Ladder[from]; int& foundWordStep = g_Ladder[mid]; if ((foundWordStep < currentWordStep + 1)) { foundWordStep = currentWordStep + 1; if (m_Longest < foundWordStep) { m_Longest = foundWordStep; } } break; } else if (0 < cmp) { right = mid - 1; } else { left = mid + 1; } } } int CEditStepLadder::GetLongestEditStepLadder() { vector<char> letter; letter.reserve(26); for (char c = 'a'; c <= 'z'; ++c) { letter.push_back(c); } const int letterSize = (int)letter.size(); string originalWord; string word; for (int it = 0; it < m_WordSize; ++it) { originalWord = g_Words[it]; word = originalWord; size_t wordSize = word.size(); // ํ ๊ธ์๊ฐ ๋ฐ๋ ๊ฒฝ์ฐ for (size_t i = 0; i < wordSize; ++i) { word = originalWord; // reset for (int j = 0; j < letterSize; ++j) { word[i] = letter[j]; Find(it, word); } } // ํ ๊ธ์๋ฅผ ๋ํ ๊ฒฝ์ฐ. // 3 ์์ง๋ฆฌ ๊ธ์๋ผ๋ฉด, ๊ธ์๊ฐ ์ถ๊ฐ๋ ์ ์๋ ๊ณณ์ 4 ๊ตฐ๋ฐ๋ค. for (size_t i = 0; i <= wordSize; ++i) { word = originalWord; // reset word.insert(word.begin() + i, ' '); for (int j = 0; j < letterSize; ++j) { word[i] = letter[j]; Find(it, word); } } // ํ ๊ธ์๋ฅผ ๋บ ๊ฒฝ์ฐ for (size_t i = 0; i < wordSize; ++i) { word = originalWord; // reset word.erase(i, 1); Find(it, word); } } return m_Longest; } /////////////////////////////////////////////////////////////// // CConsole class CConsole { public: static void ConsoleTest(istream& input, ostream& output); }; void CConsole::ConsoleTest(istream& input, ostream& output) { CEditStepLadder ladder; string word; while (input >> word) { ladder.Insert(word); } int ret = ladder.GetLongestEditStepLadder(); output << ret; }; } using namespace ATCode; #ifndef _UNIT_TEST int main() { CConsole::ConsoleTest(cin, cout); return 0; } #else // tests struct FixtureConsole { stringstream input; stringstream output; }; TEST_FIXTURE(FixtureConsole, ConsoleTest) { string s = "test"; string s1 = "test1"; CHECK(s < s1); string s2 = "aest"; string s3 = "test"; CHECK(s2 < s3); } TEST_FIXTURE(FixtureConsole, ConsoleTest1) { input << "cat\n" "dig\n" "dog\n" "fig\n" "fin\n" "fine\n" "fog\n" "log\n" "wine\n" ; CConsole::ConsoleTest(input, output); CHECK_EQUAL("5", output.str()); } #endif /* @END_OF_SOURCE_CODE */
- ๋ง์ด ๋ฆ์์ต๋๋ค. ใ
Public Class StepLadder
Function GetEditStepLadders(ByVal inputs As List(Of String)) As Integer
Dim words As List(Of Word) = CreateWordList(inputs)
CalcWordSteps(words)
Return GetMaxSteps(words)
End Function
Sub CalcWordSteps(ByVal words As List(Of Word))
Dim maxSubStep As Integer
For i As Integer = 1 To words.Count - 1
Dim aWord As Word = words(i)
For j As Integer = 0 To i - 1
Dim compared As Word = words(j)
If IsEditStep(aWord, compared) Then
If compared.Steps > maxSubStep Then maxSubStep = compared.Steps
End If
Next j
aWord.SetSteps(aWord.Steps + maxSubStep)
Next i
End Sub
Function IsEditStep(ByVal first As Word, ByVal second As Word) As Boolean
Dim str1 As String
Dim str2 As String
If first.Str < second.Str Then
str1 = first.Str
str2 = second.Str
Else
str1 = second.Str
str2 = first.Str
End If
Dim isOneModified As Boolean = IsModifiedOne(str1, str2)
Dim isOneRemoved As Boolean = IsRemovedOne(str1, str2)
Dim isOneAdded As Boolean = IsAddeddOne(str1, str2)
Return (isOneModified Or isOneRemoved Or isOneAdded)
End Function
Function IsRemovedOne(ByVal first As String, ByVal second As String) As Boolean
Dim ch1() As Char = first.ToCharArray()
Dim ch2() As Char = second.ToCharArray()
If ch1.Length <> ch2.Length + 1 Then Return False
For Each c2 As Char In ch2
If Not IsContain(c2, ch1) Then Return False
Next
Return True
End Function
Function IsContain(ByVal aChar As Char, ByVal chs() As Char) As Boolean
For Each ch As Char In chs
If aChar = ch Then Return True
Next
Return False
End Function
Function IsModifiedOne(ByVal first As String, ByVal second As String) As Boolean
Dim ch1() As Char = first.ToCharArray()
Dim ch2() As Char = second.ToCharArray()
If ch1.Length <> ch2.Length Then Return False
Dim diffCount As Integer
For i As Integer = 0 To ch1.Length - 1
If ch1(i) <> ch2(i) Then diffCount += 1
If diffCount >= 2 Then Return False
Next
Return (diffCount = 1)
End Function
Function IsAddeddOne(ByVal first As String, ByVal second As String) As Boolean
Return IsRemovedOne(second, first)
End Function
Function CreateWordList(ByVal inputs As List(Of String)) As List(Of Word)
inputs.Sort()
Dim words As List(Of Word) = New List(Of Word)
For Each str As String In inputs
words.Add(New Word(str))
Next
Return words
End Function
Function GetMaxSteps(ByVal words As List(Of Word)) As Integer
Dim maxSteps As Integer
For Each aWord As Word In words
If aWord.Steps > maxSteps Then maxSteps = aWord.Steps
Next
Return maxSteps
End Function
End Class
Public Class Word
Private _str As String
ReadOnly Property Str()
Get
Return _str
End Get
End Property
Private _steps As Integer = 1
ReadOnly Property Steps()
Get
Return _steps
End Get
End Property
Sub SetSteps(ByVal steps As Integer)
_steps = steps
End Sub
Sub New(ByVal str As String)
_str = str
End Sub
End Class
<TestClass()> _
Public Class StepLadderTest
Private _inputs As List(Of String)
Private _ladder As StepLadder = New StepLadder
Private _words As List(Of Word)
<TestInitialize()> _
Public Sub MyTestInitialize()
Dim strs() As String = {"cat", "dig", "dog", "fig", "fin", "fine", "fog", "log", "wine"}
_inputs = New List(Of String)(strs)
_words = _ladder.CreateWordList(_inputs)
End Sub
<TestMethod()> _
Public Sub SortTest()
_inputs.Sort()
Assert.AreEqual("cat", _inputs(0))
End Sub
<TestMethod()> _
Public Sub CreateWordListTest()
Assert.AreEqual(9, _words.Count)
Assert.AreEqual("cat", _words(0).Str)
End Sub
<TestMethod()> _
Public Sub IsContainTest()
Dim chs() As Char = {"a"c, "b"c}
Assert.IsTrue(_ladder.IsContain("a"c, chs))
Assert.IsFalse(_ladder.IsContain("c"c, chs))
End Sub
<TestMethod()> _
Public Sub IsRemovedOneTest()
Assert.IsTrue(_ladder.IsRemovedOne("fine", "fne"))
Assert.IsFalse(_ladder.IsRemovedOne("fin", "fine"))
Assert.IsFalse(_ladder.IsRemovedOne("fine", "fe"))
End Sub
<TestMethod()> _
Public Sub IsAddedOneTest()
Assert.IsTrue(_ladder.IsAddeddOne("fin", "fine"))
Assert.IsFalse(_ladder.IsAddeddOne("fine", "fie"))
Assert.IsFalse(_ladder.IsAddeddOne("fi", "fine"))
End Sub
<TestMethod()> _
Public Sub IsModifiedOneTest()
Assert.IsTrue(_ladder.IsModifiedOne("fig", "dig"))
Assert.IsTrue(_ladder.IsModifiedOne("fog", "dog"))
Assert.IsFalse(_ladder.IsModifiedOne("fog", "fo"))
Assert.IsFalse(_ladder.IsModifiedOne("fog", "foge"))
Assert.IsFalse(_ladder.IsModifiedOne("fog", "dig"))
End Sub
<TestMethod()> _
Public Sub IsEditStepTest()
Dim word1 As Word = New Word("fine")
Dim word2 As Word = New Word("fin")
Assert.IsTrue(_ladder.IsEditStep(word1, word2))
Assert.IsTrue(_ladder.IsEditStep(word2, word1))
Assert.IsFalse(_ladder.IsEditStep(word1, word1))
End Sub
<TestMethod()> _
Public Sub CalcWordStepsTest()
_ladder.CalcWordSteps(_words)
Assert.AreEqual("dog", _words(2).Str)
Assert.AreEqual(2, _words(2).Steps)
Assert.AreEqual("log", _words(7).Str)
Assert.AreEqual(5, _words(7).Steps)
End Sub
<TestMethod()> _
Public Sub GetEditStepLaddersTest()
Assert.AreEqual(5, _ladder.GetEditStepLadders(_inputs))
End Sub
End Class