문제

를 위한 데이터 구조,프로젝트 나는 찾아야 하는 가장 짧은 경로를 사이에 두 단어(아 "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/

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top