一、题目描述

描述:

计算两个字符串的最大公共子串(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. Python3.0 操作MySQL数据库执行SQL语句

    py3不支持MySQLdb,需要导入pymysql模块 # coding: utf-8 # Team : Quality Management Center # Author:Carson # Dat ...

  2. cpio - 存取归档包中的文件

    总览 (SYNOPSIS) cpio {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message] [-O [[user@]host:]a ...

  3. Java SE、Java EE、Java ME 三者区别

    现在一个个来分析 1. Java SE(Java Platform,Standard Edition).Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 ...

  4. 【BIEE】新建用户,并且赋予组BIconsumer,访问BIpublisher报表报错:检索数据xml时出错

    问题描述 今天新建一个用户用户查看报表,并且赋予该用户属于BIConsumer组,但是在访问报表的时候出现以下两个错: 1.xdo格式类的报表 2.RTF模板制作的报表 解决方案: 出现这个问题的原因 ...

  5. ICMP协议和ping命令

    当网络不通的情况下,通常会想到ping命令,ping一下,但是ping命令内部如何执行的,可能并不清楚,其实ping是基于ICMP协议进行工作的.  一.ICMP协议的格式 ICMP是在RFC 792 ...

  6. Oracle排名函数(Rank)实例详解

    这篇文章主要介绍了Oracle排名函数(Rank)实例详解,需要的朋友可以参考下     --已知:两种排名方式(分区和不分区):使用和不使用partition --两种计算方式(连续,不连续),对应 ...

  7. 简谈Redis

    1.为什么使用redis 分析:博主觉得在项目中使用redis,主要是从两个角度去考虑:性能和并发.当然,redis还具备可以做分布式锁等其他功能,但是如果只是为了分布式锁这些其他功能,完全还有其他中 ...

  8. Linux基础学习二

    新建分区:fdisk /dev/sda(a代表第一块硬盘)                   建完后w保存 更新分区表:partprobe mkfs.ext4 /dev/sdb{1..3} : 格式 ...

  9. php - namespace篇

    之前没有系统学习过PHP语言,直接上手TP框架了,所以认为namespace和use是TP框架的一部分,最近学习语言模块的时候遇到了这个问题,所以汇总了一下. PHP中命名空间可以解决两类问题: 用户 ...

  10. 九度教程第22题——今年暑假不AC(看尽量多的电视节目)

    #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <algorithm> using namespace ...