Python 動態規劃演算法求解最長公共子串行

2021-08-01 11:59:26 字數 4762 閱讀 4256

前言:在網上看到一道360的秋招真題,題目如下:

仔細讀題後發現這是一道求解最長公共子串行的問題,最好使用動態規劃演算法。

小b坐火車,從起點到終點的車站序列已知,期間他睡了兩覺,到終點的時候還在睡,也就是說中間他醒了兩次,這兩次清醒的時間,有兩個車站子串行,現在讓我們分析這兩段路是去的時候看到的,還是回來的時候看到的,來回都能看到,還是說壓根不存在。

一共有四種結果:

forward

backward

invalid

both

首先將兩個子串連線,判斷連線後的子串是否正好是與總串的最長公共子串行

若是,則forward驗證

然後反轉總串,再判斷連線後的子串是否正好是與總串的最長公共子串行

若是,則backward驗證

若都不是則不存在這樣的車站序列

1、最長公共子串行的結構(問題的最優子結構性質)

2、子問題的遞迴結構(建立遞迴關係)

由最優子結構性質可知,要找出x和y

的最長公共子串行可按以下方式遞迴地進行: (

1)當xm

=yn時,找出

xm-1和yn

-1的最長公共子串行。 (

2)當xm≠

yn時,必須解兩個子問題,找出

xm-1和y

的乙個最長公共子串行及x和

yn-1

的乙個最長公共子串行。這兩個公共子串行中

較長者即為x和

y的乙個最長公共子串行。

資料結構1:用c[i

][j]

記錄序列和的最長公共子串行的長度

資料結構2:用b[

i][j]

記錄當前序列和的**

(1)若c[i][j]由c[i-1][j-1]

得到,b[i][j] = 1

(2)若c[i][j]由c[i-1][j]得到,b[i][j] = 2

(3)若c[i][j]由c[i][j-1]得到,b[i][j] = 3

我的**:

# encoding :utf-8

def

lcs(k, l, slist, b):

if k == 0

or l == 0:

return

if b[k][l] == 1:

lcs(k - 1

, l - 1

, slist, b)

elif b[k][l] == 2:

lcs(k, l - 1

, slist, b)

else:

lcs(k - 1

, l, slist, b)

def

lcs2(k, l, sslist, b):

if k == 0

or l == 0:

return

if b[k][l] == 1:

lcs2(k - 1

, l - 1

, sslist, b)

elif b[k][l] == 2:

lcs2(k, l - 1

, sslist, b)

else:

lcs2(k - 1

, l, sslist, b)

while

1: fo = 0

ba = 0

s = raw_input()

a = raw_input()

b = raw_input()

ss = s[::-1]

slist = list(s)

slist.insert(0

, '0')

ablist = list(a + b)

ablist.insert(0

, '0')

sslist = list(ss)

sslist.insert(0

, '0')

c = [([0] * len(ablist)) for i in

range(len(slist))]

b = [([0] * len(ablist)) for i in

range(len(slist))]

cc = [([0] * len(ablist)) for i in

range(len(sslist))]

bb = [([0] * len(ablist)) for i in

range(len(sslist))]

# print c

# print slist

# print ablist

res =

for i in

range(1

, len(slist)):

for j in

range(1

, len(ablist)):

if slist[i] == ablist[j]:

c[i][j] = c[i - 1][j - 1] + 1

b[i][j] = 1

elif c[i - 1][j] > c[i][j - 1]:

c[i][j] = c[i - 1][j]

b[i][j] = 3

else:

c[i][j] = c[i][j - 1]

b[i][j] = 2

lcs(len(slist) - 1

, len(ablist) - 1

, slist, b)

print ablist

print res

if res[::-1] == ablist[1:]:

fo = 1

res =

for i in

range(1

, len(sslist)):

for j in

range(1

, len(ablist)):

if sslist[i] == ablist[j]:

cc[i][j] = cc[i - 1][j - 1] + 1

bb[i][j] = 1

elif cc[i - 1][j] > cc[i][j - 1]:

cc[i][j] = cc[i - 1][j]

bb[i][j] = 3

else:

cc[i][j] = cc[i][j - 1]

bb[i][j] = 2

lcs2(len(sslist) - 1

, len(ablist) - 1

, sslist, bb)

print res

if res[::-1] == ablist[1:]:

ba = 1

if fo == 1

and ba == 0:

print

"forward"

elif fo == 0

and ba == 1:

print

"backward"

elif fo == 1

and ba == 1:

print

"both"

else:

print

"invalid"

別人的**:

while 

1: a = raw_input()

b = raw_input()

c = raw_input()

e = len(b)

if (b in a) & (c in a):

bl = a.find(b)

if bl + e <= len(a) - 1:

if a.find(c, bl + e) > 0:

res = 1

else:

res = 0

else:

res = 0

else:

res = 0

d = a[::-1]

if (b in d) & (c in d):

bl = d.find(b)

if bl + e <= len(a) - 1:

if d.find(c, bl + e) > 0:

res += 2

else:

res += 0

else:

res += 0

else:

res += 0

if res == 0: print

'invalid'

if res == 1: print

'forward'

if res == 2: print

'backward'

if res == 3: print

'both'

看了人家的**才體會到什麼是差距,人家的**簡潔而又漂亮。這裡再惡補一下find函式是怎麼用的,發現沒有,有了find函式,根本就不需要寫求解最長公共子串行的函式了…

簡介:find是字串型別的成員函式

函式原型:

s.find(str, pos_start, pos_end)

解釋:

返回值:如果查到:返回查詢的

第乙個出現的位置。

否則,返回-1。

python 動態規劃演算法

你有三枚硬幣,面值分別是a 2,5,7 每種硬幣足夠多,買一本書需要x 27元,如何用最少的硬幣組合正好付清,不需要對方找錢。1.確定狀態 假設最優解為k a1 a2 ak 1.1 最後一步 假設最優解為 27 ak 1.2 子問題 求27 ak最優解f x f x 2 1 f x 5 1 f x ...

Python 動態規劃演算法

假設你是乙個小偷,背乙個可裝4磅東西的揹包。可盜竊的商品有如下3件 音響,4磅,價值3000美元 膝上型電腦,3磅,價值2000美元 吉他,1磅,價值1500美元 為了讓盜竊的商品價值最高,你該選擇哪些商品?演算法 第9章動態規劃 w 0,4,3,1 商品的重量列表,w 0 佔位用 p 0,3000...

動態規劃演算法

一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...