HJ65 查找最长公共子串
题目描述
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
数据范围:字符串长度1\le length \le300 \1≤length≤300
进阶:时间复杂度:O(n^3)\O(n3) ,空间复杂度:O(n)\O(n)
输入描述:
输入两个字符串
输出描述:
返回重复出现的字符
示例
输入:
abcdefghijklmnop
abcsafjklmnopqrstuvw
输出:
jklmnop
解题思路
通过一个二维数组记录已遍历的匹配的两个字符串的结果(单次字符匹配的结果),数组的两个下标 i 和 j 表示串1前 i 部分和串2前 j 部分匹配的长度。nmax记录目前匹配最长子串的长度,而pos为该子串尾部的位置。
代码如下:
#include <iostream> #include <string> #include <algorithm> using namespace std; int dp[301][301]; int nmax,pos; void solve(string a,string b){ for(int i=0;i<a.length();i++){ if(a[i] == b[0]){ dp[i][0] = 1; nmax = 1; pos = i; }else dp[i][0] = 0; } for(int i=0;i<b.length();i++){ if(a[0] == b[i]){ dp[0][i] = 1; nmax = 1; pos = 0; }else dp[0][i] = 0; } for(int i=1;i<a.length();i++){ for(int j=1;j<b.length();j++){ if(a[i] == b[j]){ dp[i][j] = dp[i-1][j-1] + 1; if(dp[i][j] > nmax)nmax = dp[i][j],pos = i; } else dp[i][j] = 0; } } cout<<nmax<<endl; } int main(){ string a,b; while(cin>>a>>b){ nmax = 0; if(a.length() > b.length()) swap(a,b); solve(a,b); } return 0; }