一道练习最长公共子串的题。
题意
给定两个字符串,让你求出两个字符串的最长公共子串。
解法
求最长公共子串,所以考虑动态规划,时间复杂度为 O ( n m ) O(nm) O(nm),其中 n n n 和 m m m 是两个子序列的长度。
因为动态规划时有可能访问到 − 1 -1 −1 这个地址,为防止数组越界,我们要在字符串前加上一个或多个字符防止越界。
坑点:我们不要开 int
型变量,会出锅的,要开 short
型变量。
动态规划转移方程
观察这张图,对于 a i − 1 , j − 1 \mathit{a}_{i-1,j-1} ai−1,j−1 来说,它的值有两种可能,取决于字符 x i x_i xi 和 y j y_j yj 这两个字符是否相等。
a i , j = { 0 i = 1 ∨ j = 0 a i − 1 , j − 1 + 1 i , j > 0 ∧ x i = y i 0 i , j > 0 ∧ x i ≠ y i \mathit{a}_{i,j}=\begin{cases}0&i=1 \lor j=0\\ \mathit{a}_{i-1,j-1}+1&i,j>0 \land x_i = y_i \\ 0 & i,j>0 \land x_i \ne y_i \end{cases} ai,j=⎩ ⎨ ⎧0ai−1,j−1+10i=1∨j=0i,j>0∧xi=yii,j>0∧xi=yi
代码
#include<bits/stdc++.h>
std::string s1,s2;
short f[4010][4010],ans,s1s,s2s;
int main()
{
std::cin>>s1>>s2,s1="0"+s1,s2="0"+s2,s1s=s1.size(),s2s=s2.size();
for(int i=1;i<s1s;i++) for(int j=1;j<s2s;j++) if(s1[i]==s2[j]) f[i][j]=f[i-1][j-1]+1;
for(int i=1;i<s1s;i++) for(int j=1;j<s2s;j++) ans=std::max(ans,f[i][j]);
std::cout<<ans<<std::endl;
return 0;
}