Temukan jalur terpanjang dengan BFS

Saya memiliki daftar dengan 794 kata yang panjangnya tiga huruf. Tugas saya adalah menemukan kata dengan jalur terpanjang menuju kata tertentu.

Definisi (anak-anak):
Anak-anak dari kata induk adalah kata induk dengan satu dan hanya satu huruf yang diganti.

Contoh:
'can', 'run', 'rap' dan sebagainya adalah turunan dari kata 'ran' (mengingat kata-kata tersebut ada dalam daftar).

Definisi (jalur):
Jalur adalah rangkaian kata yang setiap kata dihasilkan dengan menukar satu huruf pada kata sebelumnya.

#Pseudo code
Given a word 
    Put the word in a queue
    Keep a list with all visited words
    As long as the queue is not empty
        Get the first word in the queue
        Generate a list with all the children to this word
        For every children in that list
            If the child is not in the list of visited words
                Append the child to the list of visited words
                Put the child in the queue
    Print the path to the last grandchild.

Ide saya adalah ini akan memberikan jalur terpanjang sejak kita terus menghasilkan anak-anak baru sampai kita kehabisan kemungkinan anak-anak (yaitu, anak-anak yang belum pernah dikunjungi).

Pertanyaan:
Apakah ide saya valid? Bagaimana cara menguji apakah ini benar-benar berfungsi?


Kode sebenarnya dapat dilihat di bawah, tetapi mungkin tidak masuk akal tanpa komentar.

Edit
Karena pohon dan daftar bisa agak lambat, saya menggantinya dengan set.

from Queue import Queuenode; import Bintree
with open('word3',encoding='utf-8') as f:
    lista=f.readlines()
    lista=[x.strip('\n') for x in lista]
alfabet='abcdefghijklmnopqrstuvwxyzåäö'
class Word:
    def __init__(self, w, f = None):
        self.word = w
        self.parent = f
children=Bintree.Bintree()
for i in lista:
    children.put(i)
def barn(far):
    barnlista=[]
    for i in range(3):
        for j in range(29):
            empty=''
            empty+=far[0:i]+alfabet[j]+far[i+1:]
            if empty!=far and children._exists(empty):
                barnlista+=[empty]
    return barnlista
ko=Queuenode()
def vag(item):
    start=item
    counter=0
    while start!=None:
        counter+=1
        print(start.word)
        start=start.parent
    print(counter)
def bfsx(startord):
    ko.put(Word(startord))
    besokta=[startord]
    while not ko.isempty():
        first=ko.get()
        lista=barn(first.word)
        for child in lista:
            if child not in besokta:
                besokta+=[child]
                ko.put(Word(child,first))
    vag(first)

person Lozansky    schedule 19.09.2016    source sumber


Jawaban (1)


IIUC, ini tidak dijamin berhasil (pada kenyataannya, Anda dapat membuat kasus yang tidak berhasil).

Misalkan Anda memulai pada simpul a; ada jalur langsung a b; ada juga jalur langsung a c dan jalur tidak langsung c b.

Misalkan ketika Anda melakukan iterasi pada anak a, Anda menemukan b sebelum c. Anda berurusan dengan b dan menandainya sebagai telah dikunjungi. Suatu saat nanti Anda akan menemukan c, dan pada akhirnya mempertimbangkan kembali b. Namun, pada saat itu, b sudah dianggap dikunjungi, sehingga algoritme Anda akan mempertimbangkan subjalur a b yang lebih pendek daripada subjalur yang lebih panjang a c b.

Anda juga tidak dapat menghilangkan tanda "dikunjungi", karena cerita di balik grafik Anda memperjelas bahwa itu bukan DAG. Jika Anda menghapus logika "mengunjungi", Anda akan menemukan loop tak terbatas.

person Ami Tavory    schedule 19.09.2016
comment
Tampaknya itu adalah poin yang valid. Saya akan memperbarui dengan ide baru. - person Lozansky; 19.09.2016
comment
Sebenarnya, menurut saya maksud Anda mungkin tidak valid. Hal ini karena ketika kita menghasilkan anak-anak ke a (yaitu b dan c) kita perlu melacaknya agar tidak terjebak dalam satu lingkaran. Jadi ketika b dan c telah dihasilkan, seharusnya tidak ada cara bagi c untuk menghasilkan b sebagai anak. - person Lozansky; 19.09.2016
comment
@Lozansky Saya tidak mengikuti maksud Anda, atau, lebih tepatnya, itulah maksud yang ingin saya sampaikan. Misalkan seseorang menunjukkan kepada Anda jalur terpanjang dalam grafik, dan itu adalah a->c->b->d. Kemudian, jika dipikir-pikir, ketika algoritme Anda menemukan b sebagai anak pertama dari a, sebaiknya lewati saja dan tunggu hingga tercapai dari c. Masalahnya adalah algoritme tidak mengetahuinya - algoritme akan menandai b sebagai telah dikunjungi, dan tidak setuju untuk mempertimbangkan jalur ini. Jika saya melewatkan sesuatu, silakan tunjukkan. - person Ami Tavory; 19.09.2016
comment
Saya rasa saya memahami alasan Anda, tetapi saya merasa sulit untuk menerapkan ide tersebut dalam praktik. Bagian yang sulit tampaknya adalah kapan harus menambahkan sebuah kata ke kumpulan kata yang dikunjungi. Saya akan sangat berterima kasih atas sedikit bimbingan kecil. - person Lozansky; 19.09.2016
comment
@Lozansky Saya tidak tahu bagaimana menyelesaikannya - saya tidak menyembunyikan informasi apa pun. - person Ami Tavory; 19.09.2016
comment
Oke, terima kasih atas bantuan Anda! Saya akan bertanya mencoba mendapatkan klarifikasi tentang masalah ini besok dan jika saya menyelesaikannya dan jika Anda tertarik saya akan mengirimkan solusinya. - person Lozansky; 19.09.2016
comment
@Lozansky Tentu. Jadi caranya adalah jika sudah menemukan solusi, bisa dituliskan sebagai jawaban (tidak ada masalah jika menjawab pertanyaan sendiri). Orang yang tertarik dengan pertanyaan tersebut dapat menandainya, dan kemudian mereka melihat perubahannya. - person Ami Tavory; 19.09.2016
comment
Solusi saya sebenarnya benar, karena mereka ingin kami menemukan jalur terpendek dan terpanjang antara dua node (jika itu masuk akal). Maaf bila membingungkan! - person Lozansky; 20.09.2016
comment
@Lozansky Oh, senang Anda akhirnya berhasil. FWIW, menurut saya penafsiran masalah yang lain cukup sulit. Semua yang terbaik. - person Ami Tavory; 20.09.2016