第一次寫這種,為了學習,有錯直言,見諒
我們稱z=是序列x=的子串行當且僅當存在嚴格上公升的序列使得j=1,2,3,...k,有xij=zj。
例子說明子串行: 如果a=,b=,那麼b就是a的乙個子串行,當然還有其他的子串行.
最大公共子學列:如果給出兩個序列x,y,就是要找到乙個最長的子串行z,使其既是x的子串行,也是y的子串行。
應該就需要這兩個概念吧。。
然後是遞推關係
if(i == 0 || j == 0)
else if(s1[i] == s2[i])
else
說明s1,s2是存放兩個字串的陣列,字元標號從1開始方便理解,比如asd中的第2個字元是s。maxlen(i,j)是s1i和s2j構成的最長公共子串行的長度
maxlen(i,j)=0,表示兩個空串的最長公共子串行的長度是0.
其中else 的遞推關係maxlen(i,j) = max(maxlen(i,j-1),maxlen(i-1,j));中一定有乙個是比maxlen(i,j)大的
需要用反證法證明 在s1和s2中maxlen(i,j) 不可能比maxlen(i,j-1)和maxlen(i-1,j)都大。
比如假設一:maxlen(i,j)比maxlen(i,j-1)大,i不變,那一定是s1[i]的作用,也就是說s1[i]肯定是最長公共子串行的最後乙個字元。
二:maxlen(i,j)比maxlen(i-1,j)大,j不變,那一定是s2[j]的作用。也就是說s2[j]肯定是最長公共子串行的最後乙個字元。
那麼s1[i]==s2[j]。與else不符。所以遞推關係成立 。也可以找簡單的兩個字串試試
再就是模板
for(int i=0; i<=len1; i++)//初始化dp陣列
dp[i][0]=0;
for(int i=0; i<=len2; i++)
dp[0][i]=0;
for(int i=1; i<=len1; i++)
}} printf("%d\n",dp[len1][len2]);//輸出最長公共子串行
} return 0;
}
附一道例題
所謂回文字串,就是乙個字串,從左到右讀和從右到左讀是完全一樣的,比如"aba"。當然,我們給你的問題不會再簡單到判斷乙個字串是不是回文字串。現在要求你,給你乙個字串,可在任意位置新增字元,最少再新增幾個字元,可以使這個字串成為回文字串。
第一行給出整數n(0
接下來的n行,每行乙個字串,每個字串長度不超過1000.
每行輸出所需新增的最少字元數
1ab3bd
2本題只給出乙個字串,用到頭檔案#include裡的reverse逆置字串。
要求每行輸出所需新增的最少字串數,轉化成求原字串與其逆置字串的最長公共子串行的長度,
然後用原字串的長度減去最長公共子串行的長度就是應該新增的字串數
#include#include#includeusing namespace std;
int dp[1005][1005];
char s1[1005];
char s2[1005];
int main()
for(i=1;i<=len;i++)//動規核心
} printf("%d\n",len-dp[len][len]);
} return 0;
}
參考資料《程式設計導引》以及學長的** 2017.8.20 動態規劃 最長公共子串行
問題描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在嚴格上公升的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給出兩個序列x和y,你的任務是找到x和y的最大公共子串行,也就是說要...
動態規劃 最長公共子串行
兩個序列的最長公共子序 lcs longest common length 的 每個字元可以不連續,如x y 那麼它們的最長公共子串行為。這是乙個經典的動態規劃問題,著手點還是找到 最精髓的 狀態轉移方程 假設x,y兩個序列的前i,j個位置的最大子串行已經找到為r i j 自底往上 那麼x i 與y...
動態規劃 最長公共子串行
看完演算法導論關於這部分內容之後的總結 關於最長公共子串行問題 給定兩個子串行 x y 求x和y長度最長的公共子串行。解決方法 首先先要了解lcs的最優子結構,令x y 為兩個子串行,z 為x和y的任意lcs。1 如果 xm yn 則 zk xm yn 且 zk 1 是 xm 1 和 yn 1 的乙...