20101106 動態規劃訓練 字串距離

2021-06-26 20:30:55 字數 3675 閱讀 7011

源程式名            blast.???(pas, c, cpp)

可執行檔名        blast.exe

輸入檔名          blast.in

輸出檔名          blast.out

【問題描述】

設有字串x,我們稱在x的頭尾及中間插入任意多個空格後構成的新字串為x的擴充套件串,如字串x為」abcbcd」,則字串「abcb□cd」,「□a□bcbcd□」和「abcb□cd□」都是x的擴充套件串,這裡「□」代表空格字元。

如果a1是字串a的擴充套件串,b1是字串b的擴充套件串,a1與b1具有相同的長度,那麼我捫定義字串a1與b1的距離為相應位置上的字元的距離總和,而兩個非空格字元的距離定義為它們的ascii碼的差的絕對值,而空格字元與其他任意字元之間的距離為已知的定值k,空格字元與空格字元的距離為0。在字串a、b的所有擴充套件串中,必定存在兩個等長的擴充套件串a1、b1,使得a1與b1之間的距離達到最小,我們將這一距離定義為字串a、b的距離。

請你寫乙個程式,求出字串a、b的距離。

【輸入】

輸入檔案第一行為字串a,第二行為字串b。a、b均由小寫字母組成且長度均不超過2000。第三行為乙個整數k(1≤k≤100),表示空格與其他字元的距離。

【輸出】

輸出檔案僅一行包含乙個整數,表示所求得字串a、b的距離。

【樣例】

blast.in                                       blast.out

cmc                                           10

snmn

【演算法分析】

字串a和b的擴充套件串最大長度是a和b的長度之和。如字串a為「abcbd」,字串b為「bbcd」,它們的長度分別是la=5、lb=4,則它們的擴充套件串長度最大值為la+lb=9,即a的擴充套件串的5個字元分別對應b的擴充套件串中的5個空格,相應b的擴充套件串的4個字元對應a的擴充套件串中的4個空格。例如下面是兩個字串的長度為9的擴充套件串:

a□b c□b□d□

□b□□b□c□d

而a和b的最短擴充套件串長度為la與lb的較大者,下面是a和b的長度最短的擴充套件串:

a b cbd

b□bcd

因此,兩個字串的等長擴充套件串的數量是非常大的,尋找最佳「匹配」(對應位置字元距離和最小)的任務十分繁重,用窮舉法無法忍受,何況本題字串長度達到2000,巨大的資料規模,勢必啟發我們必須尋求更有效的方法:動態規劃。

記1, a2, …, ai>為a串中a1到ai的乙個擴充套件串,1,b2, …, bj>為b串中b1到bj的乙個擴充套件串。這兩個擴充套件串形成最佳匹配的條件是(1)長度一樣;(2)對應位置字元距離之和最小。

首先分析擴充套件串1, a2, …, ai>與擴充套件串1, b2, …, bj>長度一樣的構造方法。擴充套件串1,a2, …, ai>與擴充套件串1, b2, …, bj>可以從下列三種情況擴張成等長:

(1)1, a2, …, ai>與1, b2, …, bj

-1>為兩個等長的擴充套件串,則在1, a2, …, ai>後加一空格,1, b2, …, bj

-1>加字元bj;

(2)1, a2, …, ai

-1>與1, b2, …, bj>為兩個等長的擴充套件串,則在1,a2, …, ai

-1>新增字元ai,在1, b2, …, bj>後加一空格;

(3)1, a2, …, ai

-1>與1, b2, …, bj

-1>為兩個等長的擴充套件串,則在1, a2, …, ai

-1>後新增字元ai,在1,b2, …, bj

-1>後新增字元bj。

其次,如何使擴充套件成等長的這兩個擴充套件串為最佳匹配,即對應位置字元距離之和最小,其前提是上述三種擴充套件方法中,被擴充套件的三對等長的擴充套件串都應該是最佳匹配,以這三種擴充套件方法形成的等長擴充套件串(a1, a2, …, ai>和1, b2, …, bj>也有三種不同情形,其中對應位置字元距離之和最小的是最佳匹配。

為了能量化上述的構造過程,引入記號g[i, j]為字串a的子串a1, a2, …, ai與字串b的子串b1, b2, …, bj的距離,也就是擴充套件串1, a2, …, ai>與擴充套件串1, b2, …, bj>是乙個最佳匹配。則有下列狀態轉移方程:

g[i, j]=min  0≤i≤la  0≤j≤lb

其中,k位字元與字元之間的距離;為字元ai與字元bi的距離。

初始值:g[0, 0]=0    g[0, j]=j·k  g[i, 0]=i·k

綜上所述,本題的主要演算法如下:

(1)資料結構

var a, b:array[1..2000]of byte;   

g:array[0..2000, 0..2000]oflongint;  

(2)讀入字串a、b,轉換為ascii碼

la:=0;   lb:=0;

whilenot(eoln(f)) do         

begin                       

read(f, c);

inc(la);

a[la]:=ord(c);

end;

readln(f);

whilenot(eoln(f)) do

begin

read(f, c);

inc(lb);

b[lb]:=ord(c);

end;

readln(f);

(3)根據狀態轉移方程求g[la, lb]

g[0,0]:=0;

fori:=1 to la do g[i, 0]:=k+g[i-1, 0];

forj:=1 to lb do g[0, j]:=k+g[0, j-1];

fori:=1 to la do

for j:=1 to lb do

begin

g[i, j]:=k+g[i-1,j];

temp:=g[i, j-1]+k;

if g[i, j]>temp theng[i, j]:=temp;

temp:=g[i-1,j-1]+abs(a[i]-b[j]);

if g[i, j]>temp theng[i, j]:=temp;

end;

(4)輸出

writeln(f, g[la, lb]);

#include#include#include#includeusing namespace std;

const int maxn=2010;

char a[maxn];

char b[maxn];

int g[maxn][maxn]=;//陣列g儲存狀態

int k;

int main(void)

// printf("\n");

} printf("%d\n",g[a1][b1]);

return 0;}/*

a1,b1具有相同的長度 相應位置上的距離

空格和非空格之間的差為k

可以轉化為相互對應問題

a1與b1之間的字元相互對應

a[i][j]表示a1的前i個字元與b1的前j個字元對應時的最小距離和

則a[i][j]=

關鍵的問題在於如何表示a1、b1具有相同長度這個狀態

*/

動態規劃訓練題1

小可可選修了基礎生物基因學。教授告訴大家 super samuel 星球上 kitty貓的基因的長度都是 2 的正整數次冪 全是由兩種不同的基因單元組成的。這兩種不同的基因單元分別記成 0 和 1,於是 kitty 貓基因可以寫成乙個 01 串表示式 為了便於分析和降低資料儲存量,教授發明了 abc...

動態規劃訓練日記

1.洛谷p1244青蛙過河 lgp1244青蛙過河 動態規劃 狀態表示 dp i j 表示石墩數量為i,荷葉數量為j時能夠走過青蛙的數量。狀態轉移 因為青蛙在石墩上必須按照漢諾塔的形式排列。所以要從起點走到終點,必須要讓編號最大的青蛙,先跳過去。為了這個目的,我們需要把編號最大的青蛙上面的青蛙全部挪...

動態規劃訓練之十九

題目大意 o n 求出乙個序列的本質不同的子串行個數 考慮動態規劃 dp i 表示前i位子序列的個數 很顯然如果沒有本質不同的話,子串行個數等同於子集的個數就是2n 1 但關鍵就在於這個本質不同?怎麼辦?當然考慮容斥 記vis a i 表示上一次a i 出現的位置 只要dp的時候減掉dp vis a...