一、题目描述

描述:

计算两个字符串的最大公共子串(Longest Common Substring)的长度,字符区分大小写。

输入:

输入两个字符串

输出:

输出一个整数

样例输入:

asdfas werasdfaswer

样例输出:

6

二、解题报告

与最长公共子序列(参见《动态规划DP》)一样,最长公共子串也可以使用动态规划解决,只不过思路不太一样。准确地说,是打表的方式不一样。

举个例子:s1 = bab,s2 = caba。表如下

具体打表的方法是:

  • 第一行、第一列初始化为 0;
  • 对于其他的格子:
    • 若对应的两个字符相等,格子的值设为左上角的值加 1。
    • 若对应的两个字符不相等,直接置 0 。

这样的话,表中的最大元素就是 最长公共子串 的长度。并且也可以很容易看出最长公共子串有 2 个,分别是baab

C++代码如下:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std; int getLCStringLength(string s1, string s2)
{
if(s1 == "" || s2 == "")
return 0; int m = s1.size();
int n = s2.size();
vector<vector<int> > table(m+1, vector<int>(n+1)); int biggest = 0; // 记录表中最大值
for(int i=0; i<m+1; ++i)
{
for(int j=0; j<n+1; ++j)
{
// 第一行和第一列置0
if (i == 0 || j == 0)
table[i][j] = 0; else if(s1[i-1] == s2[j-1])
{
table[i][j] = table[i-1][j-1] + 1;
if(table[i][j] > biggest)
biggest = table[i][j];
} else // 不相等置0
table[i][j] = 0;
}
}
return biggest;
} int main ()
{
string input, s1, s2;
getline(cin, input);
stringstream ss(input);
ss >> s1;
ss >> s2;
cout << getLCStringLength(s1, s2) << endl; return 0;
}

三、扩展

如何输出所有的最长公共子串?

很简单,我们记录下 s1 和 s2 的公共子串分别在 s1 、s2 中起始位置(即表中值为 1 的坐标)。打表完成以后,我们已经知道了最长公共子串的长度length,通过substr()判断即可:

s1.substr(i-1, length) == s2.substr(j-1, length)

C++代码如下:

#include <iostream>
#include <string>
#include <vector>
using namespace std; void printLCString(string s1, string s2)
{
if(s1 == "" || s2 == "")
return; int m = s1.size();
int n = s2.size();
vector<vector<int> > table(m+1, vector<int>(n+1)); int biggest = 0; // 记录表中最大值
vector<pair<int, int> > firstPos; // 记录子串开始的坐标
for(int i=0; i<m+1; ++i)
{
for(int j=0; j<n+1; ++j)
{
// 第一行和第一列置0
if (i == 0 || j == 0)
table[i][j] = 0;
else if(s1[i-1] == s2[j-1])
{
table[i][j] = table[i-1][j-1] + 1;
if(table[i][j] > biggest)
biggest = table[i][j];
if(table[i][j] == 1)
firstPos.push_back(make_pair(i, j));
}
else // 不相等置0
table[i][j] = 0;
}
} // 输出所有的最长公共子串
vector<pair<int, int> >::iterator beg = firstPos.begin();
for( ; beg!=firstPos.end(); ++beg)
{
int start1 = beg->first-1;
int start2 = beg->second-1;
if(s1.substr(start1, biggest) == s2.substr(start2, biggest))
cout << s1.substr(start1, biggest) << endl;
}
} int main ()
{
string s1 = "hello,world,james";
string s2 = "james is saying hello";
printLCString(s1, s2); return 0;
}

个人站点:http://songlee24.github.com

华为OJ2011-最长公共子串的更多相关文章

  1. 华为OJ之最长公共子串

    题目描述: 对于两个给定的字符串,给出他们的最长公共子串. 题目分析: 1,最长公共子串(LCS)实际上是最长公共子序列的一种特殊情况,相当于是求连续的最长子序列.我们今天先解决这个特殊情况,后续博文 ...

  2. 最长公共子串(Longest common substring)

    问题描述: 给定两个序列 X=<x1, x2, ..., xm>, Y<y1, y2, ..., yn>,求X和Y长度最长的公共子串.(子串中的字符要求连续) 这道题和最长公共 ...

  3. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  4. HDU 1503 带回朔路径的最长公共子串

    http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...

  5. 最长公共子序列PK最长公共子串

    1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...

  6. 动态规划(一)——最长公共子序列和最长公共子串

    注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...

  7. 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

    Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...

  8. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

  9. 最长公共子串 NYOJ 36

    http://acm.nyist.net/JudgeOnline/problem.php?pid=36 最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 ...

随机推荐

  1. Android(java)学习笔记196:ContentProvider使用之内容观察者01

    1. 内容观察者 不属于四大组件,只是内容提供者ContentProvider对应的小功能. 如果发现数据库内容变化了,就会立刻观察到. 下面是逻辑图:       当A应用中银行内部的数据发生变化的 ...

  2. vue组件之this指向问题

    [问题描述] 返回顶部组件里,用到数据操作.通过方法里改动this数据,但发现直接使用失效 mounted() { window.onscroll=function(){ ) { this.isAct ...

  3. 【JavaScript从入门到精通】第三课

    第三课 初探JavaScript魅力-03 函数传参 上节课的时候我们已经讲了什么是函数,实际上,函数在功能上就类似于css的class一样,将一段代码包裹起来使用.为了让函数的功能更加的丰富和实用, ...

  4. Linux 内核框架图

  5. centos6 rpm安装mysql(5.5版本)包括 error : Failed dependencies:libaio的解决办法.

    1.先在/opt目录下放了两个rpm包 2.先看系统中是否有其他版本的mysql的rpm包 rpm -qa | grep -i mysql 命令结果如下图: 如果没有此步跳过,否则执行一下命令将其删除 ...

  6. Yii 2.0版本调试输出SQL语句

    项目是基于框架Yii 2.0开发的. 今天梳理一些数据统计功能代码的时候,想把当前运行的sql语句打印出来,然后放到navicat工具里面运行,并分析一下运行效率和调优方案,之前大部分时候都是写增加. ...

  7. LeetCode(70) Climbing Stairs

    题目 You are climbing a stair case. It takes n steps to reach to the top. Each time you can either cli ...

  8. 动态创建div(鼠标放上显示二维码)

    最近的微信大行其道.各个网站上都给出的微信验证码,进行手机扫描加入. 怎么创建类似与点击鼠标弹出一个浮动的div显示二维码的这种效果. 1.首先制作好这样的图片,写css样式 <style ty ...

  9. Leetcode 212.单词搜索II

    单词搜索II 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻&q ...

  10. hihoCoder#1077 RMQ问题再临-线段树

    原题地址 终于做到线段树的题了,因为建树.更新.查询都是递归操作,所以其实挺好写的. 用数组存的树,记得MAX_NODE开成两倍叶节点数大小,否则RE啊..不要问我是怎么知道的. 代码: #inclu ...