C语言 · 最长公共子序列 · 最长字符序列
如果存在一个严格递增而且长度大于0的下标序列{i1,i2……ik},使得对所有的j=1,2,……k,有x(ij)=z(j),那么我们称Z是X的字符子序列。而且,如果Z既是X的字符子序列又是Y的字符子序列,那么我们称Z为X和Y的公共字符序列。
在我们今天的问题中,我们希望计算两个给定字符序列X和Y的最大长度的公共字符序列,这里我们只要求输出这个最大长度公共子序列对应的长度值。
举例来说,字符序列X=abcd,Y=acde,那么它们的最大长度为3,相应的公共字符序列为acd。
aedfhb

/*
递归思路:
当数组a和b对应位置字符相同时,则直接求解下一个位置;
否则,取两种情况中的较大数值。
*/
#include<stdio.h>
#include<string.h>
char a[],b[];//定义字符串数组
int lena,lenb,lenz=;
int maxlong(int i,int j){
if(i>=lena || j>=lenb) return ;//出口
if(a[i] == b[j]) return +maxlong(i+,j+);//直接求解下一个位置
else //取两种情况中的较大数值
return maxlong(i+,j) > maxlong(i,j+) ? maxlong(i+,j) : maxlong(i,j+);
}
int main(){
scanf("%s%s",&a,&b);//输入字符串
lena=strlen(a);//获取字符串长度
lenb=strlen(b);
printf("%d",maxlong(,));//输出子串长度
return ;
}
动态规划:时间复杂度大大降低。

#include<stdio.h>
#include<string.h>
char a[],b[];
char num[][];//记录中间结果的数组
//动态规划采用二维数组来标识中间计算结果,避免重复的计算来提高效率
void LCS(int lena,int lenb){
for(int i=;i<=lena;i++){
for(int j=;j<=lenb;j++){
if(a[i-]==b[j-]){//注意这里的下标是i-1与j-1
num[i][j]=num[i-][j-]+;
}
else{
num[i][j]=num[i][j-] > num[i-][j] ? num[i][j-] : num[i-][j];
}
}
}
}
int main(){
scanf("%s%s",&a,&b);//输入字符串
int lena = strlen(a);//获取字符串长度
int lenb = strlen(b);
memset(num,,sizeof(num));//数组赋初值
LCS(lena,lenb);
printf("%d",num[lena][lenb]);
return ;
}
求两字符串的最长子串,有两种情况:一种是不要求在原串中连续(即上述情况),另一种要求子串在原字符串中是连续的。
下面转载了网上的方法来做另一种情况的。
用矩阵来记录中间结果:例如原串"bab"和"caba",则数组如下:
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
则矩阵的斜对角线最长的那个就是我们找的最长公共子串——求最长的由1组成的斜对角线:当要在矩阵是填1时让它等于其左上角元素加1,如下:
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这样矩阵中的最大元素就是 最长公共子串的长度。
在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵(降低空间复杂度)。
以下代码来自网络:
1 #include<iostream>
2 #include<cstring>
3 #include<vector>
4 using namespace std;
5 //str1为横向,str2这纵向
6 const string LCS(const string& str1,const string& str2){
7 int xlen=str1.size(); //横向长度
8 vector<int> tmp(xlen); //保存矩阵的上一行
9 vector<int> arr(tmp); //当前行
10 int ylen=str2.size(); //纵向长度
11 int maxele=0; //矩阵元素中的最大值
12 int pos=0; //矩阵元素最大值出现在第几列
13 for(int i=0;i<ylen;i++){
14 string s=str2.substr(i,1);
15 arr.assign(xlen,0); //数组清0
16 for(int j=0;j<xlen;j++){
17 if(str1.compare(j,1,s)==0){
18 if(j==0)
19 arr[j]=1;
20 else
21 arr[j]=tmp[j-1]+1;
22 if(arr[j]>maxele){
23 maxele=arr[j];
24 pos=j;
25 }
26 }
27 }
28 tmp.assign(arr.begin(),arr.end());
29 }
30 string res=str1.substr(pos-maxele+1,maxele);
31 return res;
32 }
33 int main(){
34 string str1("21232523311324");
35 string str2("312123223445");
36 string lcs=LCS(str1,str2);
37 cout<<lcs<<endl;
38 return 0;
39 }
最长公共子序列应用
有这样的题目:
回文串是指正反都相同的字符串,比如abba,他正着看反着看都相同,给你一个字符串,长度小于1000,让你删除最少的字符使得该字符串成为回文串,例子:agddgca,删除字符c就可以组成一个回文串。问最少删除几个字符?
想到可以借助最长公共子序列来解决,我们那上面那个例子看一下,我们把这个字符转倒序:acgddga,可以看到他们的最长公共子序列刚好是最长回文串。其实倒过来的字符串和原来的字符串比较,就是那前面的跟后面的字符串比较,如果一样,那么他们就是回文了。
所以求解这道题就比较简单了:
1)先将字符串倒序排列
2)求两个字符串飞串的最长公共子序列
3)用字符串的长度减去最长公共子序列就得到结果
C语言 · 最长公共子序列 · 最长字符序列的更多相关文章
- 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...
- 《算法导论》读书笔记之动态规划—最长公共子序列 & 最长公共子串(LCS)
From:http://my.oschina.net/leejun2005/blog/117167 1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要 ...
- 最长公共子序列&最长公共子串
首先区别最长公共子串和最长公共子序列 LCS(计算机科学算法:最长公共子序列)_百度百科 最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 最长公共子序列: http ...
- 动态规划——最长公共子序列&&最长公共子串
最长公共子序列(LCS)是一类典型的动归问题. 问题 给定两个序列(整数序列或者字符串)A和B,序列的子序列定义为从序列中按照索引单调增加的顺序取出若干个元素得到的新的序列,比如从序列A中取出 A ...
- 简单动态规划——最长公共子序列&&最长回文子序列&&最长上升||下降子序列
最长公共子序列,顾名思义当然是求两个字符串的最长公共子序列啦,当然,这只是一道非常菜的动规,所以直接附上代码: #include<iostream> #include<cstdio& ...
- [BZOJ2423][HAOI2010]最长公共子序列
[BZOJ2423][HAOI2010]最长公共子序列 试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x ...
- [Python]最长公共子序列 VS 最长公共子串[动态规划]
前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- 准备NOIP2017 最长公共子序列(模版)
一些概念: (1)子序列: 一个序列A = a1,a2,--an,中任意删除若干项,剩余的序列叫做A的一个子序列.也可以认为是从序列A按原顺序保留任意若干项得到的序列.例如: 对序列 1,3,5, ...
随机推荐
- 带你开发一款给Apk中自己主动注入代码工具icodetools(开凿篇)
一.前言 从这篇開始咋们開始一个全新的静态方式逆向工具icodetools的实现过程.这个也是我自己第一次写的个人认为比較实用的小工具,特别是在静态方式逆向apk找关键点的时候.兴许会分为三篇来具体介 ...
- C#操作Sqlite快速入门及相关工具收集
Sqlite不需要安装即可使用.Sqlite是不是那个System.Data.SQLite.DLL临时创建了数据库引擎? 1.新建一个WinForm项目,引用System.Data.SQLite.DL ...
- sqlserver数据库18456错误怎么解决?
1.以windows验证模式进入数据库管理器. 2.右击sa,选择属性: 在常规选项卡中,重新填写密码和确认密码(改成个好记的).把强制实施密码策略去掉. 3.点击状态选项卡:勾选授予和启用.然后确定 ...
- FIR定点提高精度的trick_02
作者:桂. 时间:2018-02-05 19:36:08 链接:http://www.cnblogs.com/xingshansi/p/8419182.html 一.概述 本文简要记录FIR的小tr ...
- Node.js使用rabbitMQ(一)
目前使用的开发环境主要还是win,所以也只是介绍在win下的rabbitMQ的使用. 一.安装rabbitMQ(Installing on Windows) 关于安装地址,参见:Installing ...
- Gitlab Runner的使用(涵盖gitlab-page)
#gitlab-runner 的简单安装和部署##背景 因为公司要使用CI 功能,已经使用gitlab-page的功能能,所以这里记录一下 ###安装步骤: 参考官方文档:https://doc ...
- 定时删除elasticsearch的index
#!/bin/bashfind /data/elasticsearch/data/kz-log/nodes/0/indices/ -type d -mtime +5 | awk -F"/& ...
- 权限管理系统(五):RBAC新解,基于资源的权限管理
本文讨论以角色概念进行的权限管理策略及主要以基于角色的机制进行权限管理是远远不够的.同时我将讨论一种我认为更好的权限管理方式. 1.什么是角色 当说到程序的权限管理时,人们往往想到角色这一概念.角色是 ...
- iOS安全攻防(十八):数据保护API
数据保护API 题外话 开篇先扯几句题外话,许多朋友都问我怎么不写防啊,我确实有点犹豫.hackers总是想象如果自己是开发者会怎么写,然后才能找到入手点.同理,开发者们也要想象自己是hackers会 ...
- andrdoid内置视频文件
这种方法仅仅适合有内置存储的情况,至于和平分区的不在考虑之列 1 在vendor/sprd下新建一个目录built_in_video 里边放置要内置的视频文件及copy脚步 脚步例如以下:intern ...