题名:最长公共子串
题目描述:
输入为两行可能包含空格的字符串,输出它们的最长公共连续子串的长度。
解题思路:
比较常规的想法是两个for循环加一个while循环,时间复杂度为n的三次方。这是我在一个面试中遇到的题目,当时就傻乎乎地写了常规的解法,主要是由于经验不足,想不到动态规划的方向上去。时间上的优化一般要以牺牲空间为代价,我们可以用一个二维数组dp[N][N]来存储状态,dp[i][j]表示以s1[i]和s2[j]为结尾的最长公共子串的长度,如果s1[i]等于s2[j],则dp[i+1][j+1] = dp[i][j] + 1,因为子串得以延续。
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define N 100
int main(){
int ans = 0;
string s1, s2;
getline(cin, s1);
getline(cin, s2);
/*另一种读入带空格字符串的方式
char s2[N], s2[N];
cin.getline(s1, N, '\n');
cin.getline(s2, N, '\n')
strlen(s1)取代s1.size()获取字符串长度
*/
int dp[N][N];
for(int i = 0; i < s1.size(); i++){
for(int j = 0; j < s2.size(); j++){
if(s1[i] == s2[j]){
if(i >= 1 && j >= 1){
dp[i][j] = dp[i-1][j-1] + 1;
}
else{
dp[i][j] = 1; //相当于一个初始化
}
}
ans = max(ans, dp[i][j]); //因为只对dp[i][j]做了修改
}
}
cout << ans << endl;
return 0;
}
一个注意要点:
输入为可能包含空格的字符串,常用的cin>>s1是没办法实现这个条件的,我在上面的代码中注明了两种实现方法。
1.使用getline()直接读入字符串。
头文件:#include <string>
原型:istream& getline ( istream &is , string &str , char delim );
delim表示遇到这个字符就停止读入,系统默认为换行符'\n'。
用例:getline(cin, s1);
2.使用cin.getline()读入char数组。
原型:cin.getline(char* s, int N(字符个数),char delim);
用例:cin.getline(s1, N, '\n');