最長公共子串
- 閱讀本文前可以先了解“動態規劃方法論”,在我之前講過的文章有講過。
動態規劃方法論
- 本文講解的題與leetcode718.最長重複子陣列,題意一模一樣,閱讀完本文以後可以去挑戰這題。
力扣連結
題目敘述:
給定兩個字串,輸出其最長公共子串的長度。
輸入
ABACCB
AACCAB
輸出
3
解釋
最長公共子串是ACC,其長度為3。
與最長公共子序列的區別
- 公共子串:字元必須是連續相等的
- 公共子序列:字元必須是相等的,可以不連續。
動態規劃思路
- 只有當兩個字串中的字元連續相等的時候,公共子串的長度才不斷增加,否則清零
- 因此,我們不難發現,公共子串問題其實是公共子序列問題的一個特殊情況
狀態變數以及其含義
- 我們延續
最長公共子序列
的思路,可以使用兩個指標變數,i
和j
來遍歷a,b字串。 - 那麼我們的
f[i][j]
代表著什麼呢?因為本題是要連續的子串,因此我們的f[i][j]
表示以a[i]
和b[j]
為結尾的公共子串的長度
遞推公式
- 那麼,我們很容易的就可以得出遞推公式:
f[i][j]=f[i-1][j-1]+1
(a[i]==b[j]
)f[i][j]=0
)(a[i]!=b[j]
)
- 邊界條件為:
f[0][j]=0
f[i][0]=0
遍歷順序:
- 顯然是從上到下,從左到右。
如何初始化?
- 處理好上面所說的邊界條件,並且根據遞推公式來進行初始化
f陣列
即可。
舉例列印dp陣列
- 舉例如如圖所示:
f[i][j]
的值如圖所示。
最終程式碼實現
#include<iostream>
#include<cstring>
using namespace std;
char a[200]="BCCABCCB";
char b[200]="AACCAB";
int f[201][201];
int main(){
int ans=0;
for(int i=1; i<=strlen(a); i++){
for(int j=1; j<=strlen(b); j++){
if(a[i-1]==b[j-1]) f[i][j]=f[i-1][j-1]+1;
ans=max(ans,f[i][j]);
}
}
printf("ans=%d\n",ans);
return 0;
}