11077 最长公共子字符串(优先做)
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC;JAVA
Description
求两个输入序列的最长的公共子字符串的长度。子字符串中的所有字符在源字符串中必须相邻。 如字符串:21232523311324和字符串312123223445,他们的最长公共子字符串为21232,长度为5。
输入格式
两行,第一行为第一个字符串X,第二行为第二个字符串Y,字符串不含空格并以回车标示结束。X和Y的串长都 不超过10000。
输出格式
两行,第一行为最长的公共子字符串的长度,第二行输出一个最长的公共子字符串。 说明: (1)若最长的公共子字符串有多个,请输出在源字符串X中靠左的那个。 (2)若最长公共子字符串的长度为0,请输出空串(一个换行符)。 如输入: 21232523311324 152341231 由于523和123都是最长的公共子字符串,但123在源串X中更靠左,因此输出: 3 123
输入样例
21232523311324 312123223445
输出样例
5 21232
提示
一,对输入字符串的处理 大家在接受数据的时候,不要用(c=getchar())!='\n'诸如此类一个字符一个字符接受,然后判断是否是回车 符号来结束一行的输入,这样的方式在你本机运行不会有问题,但OJ系统中会有错误,无法输出结果,因为 测试平台行末并非'\n'字符。这里接受数据用scanf的%s,或cin等,会自动判别结束字符的,你就不要在你 程序里专门去判别或吸收回车字符。 二,递推公式 此题和书上3.3节"最长公共子序列"描述是不同的,子序列可由不连续字符组成,但子字符串是连续的。 此题更加简单! 假设求字符串str1,str2的最长公共子串的长度. 定义f(m,n): 分别以str1[m],str2[n]结尾的最长连续公共子串的长度, 其中字符串末尾的str1[m]和str2[n]包含在最长公共子串中,即为最长公共子串的最末元素。 (这里大家思考一下,为何要这样假设子问题和子问题最优解f(m,n)? 因为子串是连续的,更大规模问题和下一级更小规模的子问题要能联系起来,而且这种联系还要越简单越好, 只有规定原先两个串的最末元素包含在最长公共子串中,这样就能联系上两个串的前缀部分(都去掉末个元 素)的最长公共子串问题。) 而对于f(m+1,n+1) 有: 1) f(m+1,n+1) = 0, if str1[m+1] != str2[n+1] 2) f(m+1,n+1) = f(m,n) + 1, if str1[m+1] == str2[n+1] 3) 另外边界情况,f(0,j)=0(j>=0), f(j,0)=0(j>=0) 而此题所求的最长公共字符串的长度即为f(m,n)整个二维数组中的最大值,注意不是填充的最后一个元素。 也不是最后一行元素的最大值,而是整个二位数组的最大值。思考一下为什么呢? 至于如何优先输出在源串X靠左的公共子串,大家自行思考。 这也容易,在你比较产生数组最大值maxlen时,就同步记录下那时在x数组中的下标位置,比如此位置叫endindex_x。 最后用这个位置在X序列中输出从X[endindex_x - maxlen + 1]元素一直到X[endindex_x]元素即可。
作者
zhengchan
代码实现
#include <iostream>
#include <string>
using namespace std;
int dp[10010][10010]; // dp[i][j]的值代表text1字符串前i个字符和text2字符串前j个字符的最长公共子字符串的长度
int main()
{
string text1,text2;
cin >> text1 >> text2;
int i,j;
int m = text1.length();
int n = text2.length();
int maxlen = 0; // 最长的长度
int maxindex = 0; // 公共字子字符串的下标
// text1的前i个字符
for(i = 0; i <= m; i++){
// text2的前j个字符
for(j = 0; j <= n; j++){
if(i==0||j==0) {
dp[i][j] = 0; // 没有公共的字符串
}
else{
if(text1[i-1] == text2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1; // 加上之前的
if(dp[i][j] > maxlen){
maxlen = dp[i][j]; // 更新最大值
maxindex = i-1; // 记录下标
}
}
else{
dp[i][j] = 0; // 不相同直接为0
}
}
}
}
cout << maxlen <<endl;
cout << text1.substr(maxindex-maxlen+1, maxlen) << endl;
return 0;
}