가장 짧은 경로를 변환하는 하나의 단어로 또 다른
-
19-09-2019 - |
문제
를 위한 데이터 구조,프로젝트 나는 찾아야 하는 가장 짧은 경로를 사이에 두 단어(아 "cat"
고 "dog"
)변경,단지 하나의 문자니다.우리가 받게 낙서 단어 목록을 사용하여 찾는 우리의 경로입니다.예를 들어:
cat -> bat -> bet -> bot -> bog -> dog
I've 문제를 해결을 사용하여 폭넓은 첫 번째 검색,하지만 무언가를 추구하는 더 나은(I 대표 사전 라).
주십시오에 대한 몇 가지 아이디어를 더 효율적인 방법(면에서 속도와 메모리).가 및/또는 도전이 바람직하다.
나는 나의 친구 중 하나(그 주니어)그리고 그는 말했다가는 no 효율적인 이 문제를 해결할 수 있습니다.그는 말을 배우는 것이 이유 때 나는 알고리즘 코스입니다.에 대한 의견을까요?
우리는 이동해야에서 말씀하는 단어입니다.우리가 갈 수 없습니다 cat -> dat -> dag -> dog
.우리는 또한 인쇄 traversal.
해결책
새로운 답변
최근 업데이트를 감안할 때, 당신은 해밍 거리를 휴리스틱으로 사용해 볼 수 있습니다. 거리를 과대 평가하지 않기 때문에 허용되는 휴리스틱입니다.
오래된 대답
계산에 사용되는 동적 프로그램을 수정할 수 있습니다 Levenshtein 거리 일련의 작업을 얻습니다.
편집 : 일정한 수의 줄이있는 경우 다항식 시간에는 문제가 해결 될 수 있습니다. 그렇지 않으면, 그것은 NP-HARD입니다 (위키 백과에 있습니다). 친구가 NP-HARD 문제에 대해 이야기하고 있다고 가정합니다.
편집 : 문자열이 길이가 같으면 사용할 수 있습니다. 해밍 거리.
다른 팁
사전 BFS 최적입이지만,실행하는 데 필요한 시간에 비례하는 크기(V+E).N 자의 사전 수은~^n 항목 곳은 알파벳 크기입니다.만약 사전에 포함되는 모든 단어 하나에해야한다는 말이 사슬에,당신은 통과 가능한 모든 단어나지 않을 것이 아무것도 찾을 수 있습니다.이것은 그래프 순회하지만,크기가 될 수 있습 기하 급수적으로 큰.
지 궁금할 가능한 경우 빠르게 작업을 수행 할-를 찾아보 구조"지능적으로"그리고 그것은 다항식 시간입니다.답은,제가 생각하는,아니다.
문제:
당신은 주어진 빠르(linear)방법을 확인하는 단어가 사전에,두 개의 단어는 u,v 고 있는지 확인하기 위해 시스 u->a1 ->a2 ->...->an ->v.
은 NP-어렵습니다.
Proof:일부 3 토 인스턴스
(p q 나지 않 r)(p 지 q r)
당신은 시작과 함께 0 000 00 체크인 가능한 경우에 갈 2 222 22.
첫 번째 문자가 될 것이다"우리가 완료",세 next 비트이 제 p,q,r 과 다음 두 가지를 제어하는 것 절입니다.
허용된 단어입니다:
- 아무것도로 시작하는 0 고만을 포함하는 0 과 1 의
- 아무것도로 시작하는 2 와 법적입니다.즉 그것은 구성하는 0 과 1 의 제외하고(그 첫 번째 문자가 2,모든 절 비트가 정의로운 설정에 따라 변수 비트,그리고 그들을 1 로 설정(그래서 이 표시는 수식은 satisfable).
- 아무것도로 시작하는 적어도 두 개의 2 개의 다음의 구성하는 0 과 1 의(regular expression:222*(0+1)*,다음과 같 22221101 지 2212001
생산 2 222 22 만 0 000 00,당신이 그것에서 이 방법:
(1)손가락으로 튀김 해당 비트 예0 100 111 네 단계가 있습니다.이 필요로를 찾는 3 토 솔루션입니다.
(2)변경 첫 번째 비트 2:2 100 111.할 수 있습니다.검증 이것은 참으로 3 토 솔루션입니다.
(3)변경 2 100 111 -> 2 200 111 -> 2 220 111 -> 2 222 111 -> 2 222 211 -> 2 222 221 -> 2 222 222.
이러한 규칙을 적용하는 당신은 속일 수 없습(확인).가 2 222 22 은 가능한 경우에만 공식 satisfable 및 검사는 NP-어렵습니다.나는 그것을 느낄 수 있도 열심히(#P 나 시험을 마스터 아마)지만 NP-경도 충분한 목적을 위해 나는 생각한다.
편집:에 관심이 있을 수도 있습니다 분리 설정 데이터 구조.이것을 사전에 그룹에는 단어에서 도달 할 수 있습니다.저장할 수 있습니다 또한 경로에서 모든 꼭지점을 뿌리거나 일부 다른 정점입니다.이렇게 하면 경로,반드는 가장 짧은 하나입니다.
효율성이 다양한 방법이 있습니다 발견 링크 - 각 단어 길이에 대한 완전한 그래프를 구성하거나 BK-Tree, 예를 들어, 친구가 맞습니다. BFS는 가장 효율적인 알고리즘입니다.
그러나 런타임을 크게 향상시키는 방법이 있습니다. 소스 노드에서 단일 BF를 수행하는 대신 그래프의 양쪽 끝에서 시작하여 프론티어 세트에서 공통 노드를 찾을 때 종료되는 두 개의 폭이 먼저 검색됩니다. . 한쪽 끝에서만 검색하면 필요한 작업의 양은 대략 절반입니다.
먼저 올바른 길이가 아닌 단어를 제거하여 조금 더 빨리 만들 수 있습니다. 제한된 사전의 더 많은 것이 CPU의 캐시에 적합합니다. 아마 모든 것.
또한, 모든 strncmp 비교 (모든 소문자를 만들었다 고 가정)는 MEMCMP 비교 또는 고정되지 않은 비교가 될 수 있습니다.
전처리 기업을 사용하고 해당 단어 길이의 작업을 하드 컴파일하거나 일반적인 단어 길이에 대한 작업의 몇 가지 최적화 변형을 굴릴 수 있습니다. 이러한 추가 비교는 순수한 unrolled 재미를 위해 '사라질'수 있습니다.
이것은 전형적인 것입니다 동적 프로그래밍 문제. 편집 거리 문제를 확인하십시오.
당신이 찾고있는 것은 편집 거리라고합니다. 여러 가지 유형이 있습니다.
에서 (http://en.wikipedia.org/wiki/edit_distance) : "정보 이론과 컴퓨터 과학에서, 두 문자 사이의 편집 거리는 그 중 하나를 다른 문자로 변환하는 데 필요한 작업의 수입니다."
Jazzy (Java Spell Check API)에 대한이 기사는 이러한 종류의 비교에 대한 훌륭한 개요를 가지고 있습니다 (비슷한 문제 - 제안 된 수정을 제공 함). http://www.ibm.com/developerworks/java/library/j-jazzy/
가장 긴 공통 후속을 찾을 수 있으므로 변경 해야하는 문자를 찾을 수 있습니다.
내 직감은 당신의 친구가 더 효율적인 해결책이 없다는 점에서 당신의 친구가 정확하다는 것입니다. 그러나 그것은 당신이 매번 사전을 다시로드한다고 가정합니다. 실행중인 공통 전환 데이터베이스를 유지하려면 솔루션을 찾는 데 더 효율적인 방법이있을 것이지만, 전환을 미리 생성하고 어떤 전환이 유용한 지 발견해야합니다 (생성 할 수 없기 때문에 어떤 전환이 유용한 지 발견해야합니다. 그들 모두!)는 아마도 그 자체의 예술 일 것입니다.
bool isadjacent(string& a, string& b)
{
int count = 0; // to store count of differences
int n = a.length();
// Iterate through all characters and return false
// if there are more than one mismatching characters
for (int i = 0; i < n; i++)
{
if (a[i] != b[i]) count++;
if (count > 1) return false;
}
return count == 1 ? true : false;
}
// 단어와 최소 체인 길이를 저장하는 대기열 항목 // 단어에 도달하려면.
struct QItem
{
string word;
int len;
};
// 가장 짧은 체인의 길이를 반환하여 '시작'에서 '대상'에 도달합니다. D는 사전입니다
int shortestChainLen(string& start, string& target, set<string> &D)
{
// Create a queue for BFS and insert 'start' as source vertex
queue<QItem> Q;
QItem item = {start, 1}; // Chain length for start word is 1
Q.push(item);
// While queue is not empty
while (!Q.empty())
{
// Take the front word
QItem curr = Q.front();
Q.pop();
// Go through all words of dictionary
for (set<string>::iterator it = D.begin(); it != D.end(); it++)
{
// Process a dictionary word if it is adjacent to current
// word (or vertex) of BFS
string temp = *it;
if (isadjacent(curr.word, temp))
{
// Add the dictionary word to Q
item.word = temp;
item.len = curr.len + 1;
Q.push(item);
// Remove from dictionary so that this word is not
// processed again. This is like marking visited
D.erase(temp);
// If we reached target
if (temp == target)
return item.len;
}
}
}
return 0;
}
// Driver program
int main()
{
// make dictionary
set<string> D;
D.insert("poon");
D.insert("plee");
D.insert("same");
D.insert("poie");
D.insert("plie");
D.insert("poin");
D.insert("plea");
string start = "toon";
string target = "plea";
cout << "Length of shortest chain is: "
<< shortestChainLen(start, target, D);
return 0;
}
복사 : https://www.geeksforgeeks.org/word-ladder-length-of-shortest-chain-to-target-word/