ค้นหาเส้นทางที่ยาวที่สุดกับ BFS

ฉันมีรายการคำยาวสามตัวอักษร 794 คำ งานของฉันคือค้นหาคำที่มีเส้นทางที่ยาวที่สุดไปยังคำที่กำหนด

คำจำกัดความ (ลูก):
ลูกของคำหลักคือคำแม่ที่มีการแทนที่ตัวอักษรตัวเดียวและตัวเดียวเท่านั้น

ตัวอย่าง:
'can', 'run', 'rap' ฯลฯ เป็นลูกของคำว่า 'ran' (เนื่องจากคำเหล่านั้นมีอยู่ในรายการ)

คำจำกัดความ (เส้นทาง):
เส้นทางคือชุดของคำที่แต่ละคำถูกสร้างขึ้นโดยการแลกเปลี่ยนตัวอักษรตัวเดียวในคำก่อนหน้า

#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.

ความคิดของฉันคือสิ่งนี้จะเป็นเส้นทางที่ยาวที่สุดนับตั้งแต่เราสร้างเด็กใหม่ต่อไปจนกว่าเราจะหมดเด็กที่เป็นไปได้ (นั่นคือ เด็กที่ยังไม่เคยไปเยี่ยม)

คำถาม:
ความคิดของฉันถูกต้องหรือไม่ ฉันจะทดสอบได้อย่างไรว่ามันใช้งานได้จริง?


สามารถดูโค้ดจริงได้ด้านล่าง แต่อาจไม่สมเหตุสมผลหากไม่มีความคิดเห็น

แก้ไข
เนื่องจากต้นไม้และรายการอาจช้าเล็กน้อย ฉันจึงแทนที่ด้วยชุดต่างๆ

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 แหล่งที่มา


คำตอบ (1)


IIUC ไม่รับประกันว่าจะใช้งานได้ (อันที่จริงคุณสามารถสร้างเคสที่ไม่สามารถใช้งานได้)

สมมติว่าคุณเริ่มต้นที่โหนด a; มีเส้นทางตรง a b; นอกจากนี้ยังมีเส้นทางตรง ac และเส้นทางอ้อม c b

สมมติว่าเมื่อคุณวนซ้ำลูกของ a คุณจะพบกับ b ก่อน c คุณจัดการกับ b และทำเครื่องหมายว่าเยี่ยมชมแล้ว เมื่อถึงจุดหนึ่งในภายหลัง คุณจะพบกับ c และในที่สุดก็จะพิจารณา b อีกครั้ง อย่างไรก็ตาม เมื่อถึงจุดนั้น b ถือว่าเข้าชมแล้ว ดังนั้นอัลกอริทึมของคุณจะพิจารณาเส้นทางย่อยที่สั้นกว่า a b แทนที่จะเป็นเส้นทางที่ยาวกว่า a c b

คุณไม่สามารถกำจัดเครื่องหมาย "เยี่ยมชมแล้ว" ได้ เนื่องจากเรื่องราวเบื้องหลังกราฟของคุณทำให้ชัดเจนว่าไม่ใช่ DAG หากคุณลบตรรกะ "เยี่ยมชม" ออก คุณจะพบกับการวนซ้ำไม่สิ้นสุด

person Ami Tavory    schedule 19.09.2016
comment
นั่นดูเหมือนจะเป็นจุดที่ถูกต้อง ฉันจะอัปเดตด้วยแนวคิดใหม่ - person Lozansky; 19.09.2016
comment
จริงๆ แล้ว ฉันคิดว่าประเด็นของคุณอาจไม่ถูกต้อง นั่นเป็นเพราะเมื่อเราสร้างลูกให้กับ a (เช่น b และ c) เราจำเป็นต้องติดตามสิ่งเหล่านี้เพื่อไม่ให้ติดอยู่ในวงวน ดังนั้นเมื่อ b และ c ถูกสร้างขึ้น ไม่ควรมีวิธีใดที่ c จะสร้าง b เมื่อยังเป็นเด็ก - person Lozansky; 19.09.2016
comment
@Lozansky ฉันไม่ได้ติดตามประเด็นของคุณหรือค่อนข้างจะเป็นประเด็นที่ฉันพยายามทำ สมมติว่ามีคนชี้ให้คุณเห็นเส้นทางที่ยาวที่สุดในกราฟ และมันจะเป็น a->c->b->d เมื่อมองย้อนกลับไป เมื่ออัลกอริทึมของคุณพบว่า b เป็นลูกคนแรกของ a ก็ควรข้ามไปและรอจนกว่าจะถึงจาก c จะดีกว่า ปัญหาคืออัลกอริทึมไม่ทราบ - มันจะทำเครื่องหมาย b ว่าเยี่ยมชมแล้ว และจะไม่ตกลงที่จะพิจารณาเส้นทางนี้ หากฉันขาดอะไรไปอย่าลังเลที่จะชี้ให้เห็น - person Ami Tavory; 19.09.2016
comment
ฉันคิดว่าฉันเข้าใจเหตุผลของคุณ แต่ฉันพบว่าเป็นการยากที่จะนำแนวคิดนี้ไปใช้ในทางปฏิบัติ ส่วนที่ยุ่งยากน่าจะเป็นเมื่อต้องเพิ่มคำลงในชุดคำที่เข้าชม ฉันจะขอบคุณมากสำหรับคำแนะนำเล็กๆ น้อยๆ - person Lozansky; 19.09.2016
comment
@Lozansky ฉันไม่รู้วิธีการแก้ปัญหานี้ - ฉันไม่ได้ปกปิดข้อมูลใด ๆ - person Ami Tavory; 19.09.2016
comment
โอเค ขอบคุณสำหรับความช่วยเหลือของคุณ! พรุ่งนี้ฉันจะขอให้พยายามชี้แจงปัญหานี้ และหากฉันแก้ไขได้และหากคุณสนใจ ฉันจะส่งวิธีแก้ไขไปให้คุณ - person Lozansky; 19.09.2016
comment
@Lozansky แน่นอน ดังนั้นวิธีที่จะทำคือ หากคุณพบวิธีแก้ปัญหา คุณสามารถเขียนมันเป็นคำตอบได้ (ไม่มีปัญหาในการตอบคำถามของคุณเอง) ผู้ที่สนใจคำถามสามารถทำเครื่องหมาย และดูการเปลี่ยนแปลงได้ - person Ami Tavory; 19.09.2016
comment
วิธีแก้ปัญหาของฉันถูกต้องจริงๆ เนื่องจากพวกเขาต้องการให้เราค้นหาเส้นทางที่สั้นที่สุดที่ยาวที่สุดระหว่างสองโหนด (ถ้านั่นสมเหตุสมผล) ขอโทษสำหรับความสับสน! - person Lozansky; 20.09.2016
comment
@Lozansky โอ้ดีใจที่คุณทำสำเร็จในที่สุด FWIW ฉันคิดว่าการตีความปัญหาอื่น ๆ นั้นค่อนข้างยาก ทั้งหมดที่ดีที่สุด - person Ami Tavory; 20.09.2016