所有不同的序列串-----LCS算法的变种
今天遇到LEETCODE的第115题: Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of S which equals T.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE"
is a subsequence of "ABCDE"
while "AEC"
is not).
Example 1:
Input: S ="rabbbit"
, T ="rabbit"
Explanation:
Output: 3
As shown below, there are 3 ways you can generate "rabbit" from S.
(The caret symbol ^ means the chosen letters)rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
Example 2:
Input: S ="babgbag"
, T ="bag"
Explanation:
Output: 5
As shown below, there are 5 ways you can generate "bag" from S.
(The caret symbol ^ means the chosen letters)babgbag
^^ ^
babgbag
^^ ^
babgbag
^ ^^
babgbag
^ ^^
babgbag
^^^
解法1:动态规划
假设已经得到了s[:i]中所有的t串f(i,t),考虑s[i]和t[-1]这2个字符,if不等:f(i+1,t)=f(i,t);else:f(i+1,t)=f(i,t)+f(i+1,t[:-1])。于是解法如下:
def dp(s,t):
if len(s)<len(t):return 0
if len(t)==1:return s.count(t)
ans=dp(s[:-1],t)
if s[-1]==t[-1]:ans+=dp(s[:-1],t[:-1])
return ans
测试中发现对比较长的S,出现了超时错误,说明时间复杂度高(O(len(s)*len(t)))。 解法2:二分法
对S进行等长分割成left,right,则结果应该=left中的数量 + right中的数量 + 跨界的数量
其中,跨界的数量 = left中的t[:1]数量*right中的t[1:]数量 + left中的t[:2]数量*right中的t[2:]数量 +...+ left中的t[:-1]数量*right中的t[-1]数量
于是解法如下:
def dp(s,t):
print(s,t)
if len(s)<len(t):return 0
if len(t)==1:return s.count(t)
n=len(s)//2
left,right=s[:n],s[n+1:]
ans=dp(left,t)+dp(right,t)
for i in range(1,len(t)):
ans+=dp(left,t[:i])*dp(right,t[i:])
return ans
测试中发现对比较长的S,出现了超时错误,说明时间复杂度高(O(len(s)*len(t)))。同时也说明跨界的数量不能直接算出的话,最好不要用二分法。 解法3:动态规划
再回到解法1,这次用二维转移矩阵,令f(i,j)=s[:i]中t[:j]的数量,考虑s[i]和t[j]这2个字符,if不等:f(i+1,j+1)=f(i,j);else:f(i+1,j+1)=f(i,j)+f(i+1,j)。于是解法如下:
def dp(s,t):res = [[0] * (len(s) + 1) for _ in range(len(t) + 1)]
res[0] = [1] * (len(s) + 1) for i, cht in enumerate(t):
for j, chs in enumerate(s):
if cht == chs:
res[i + 1][j + 1] = res[i][j] + res[i + 1][j]
else:
res[i + 1][j + 1] = res[i + 1][j] return res[-1][-1]
进一步优化为: def dp(s,t):
li=[0]*len(t)
d={}
for i in range(len(t)):
d[t[i]]=d.get(t[i],[])+[i]
for i in range(len(s)):
print(i,li,end=' ')
if s[i] in t:
for j in reversed(d[s[i]]):
if j == 0:
li[0] += 1
else:
li[j] += li[j - 1]
print(li)
return li[-1]
所有不同的序列串-----LCS算法的变种的更多相关文章
- 对LCS算法及其变种的初步研究
LCS的全称为Longest Common Subsequence,用于查找两个字符串中的最大公共子序列,这里需要注意区分子序列与子串,所谓子序列,指的是从前到后,可以跳跃元素筛选,而字串则必须连续筛 ...
- LCS算法
转自:http://hzzy-010.blog.163.com/blog/static/79692381200872024242126/ 好详细~~~也十分好理解~~~ 最长公共子序列问题(非连续的 ...
- 最大公共字串LCS问题(阿里巴巴)
给定两个串,均由最小字母组成.求这两个串的最大公共字串LCS(Longest Common Substring). 使用动态规划解决. #include <iostream> #inclu ...
- 序列最小最优化算法(SMO)-SVM的求解(续)
在前一篇文章中,我们给出了感知器和逻辑回归的求解,还将SVM算法的求解推导到了最后一步,在这篇文章里面,我们将给出最后一步的求解.也就是我们接下来要介绍的序列最小最优化算法. 序列最小最优化算法(SM ...
- 【机器学习】支持向量机(SVM)的优化算法——序列最小优化算法(SMO)概述
SMO算法是一一种启发式算法,它的基本思路是如果所有变量的解的条件都满足最优化问题的KKT条件,那么这个最优化问题的解就得到了.因为KKT条件是该优化问题的充分必要条件. 整个SMO算法包括两个部分: ...
- 笔试算法题(30):从已排序数组中确定数字出现的次数 & 最大公共子串和最大公共序列(LCS)
出题:在已经排序的数组中,找出给定数字出现的次数: 分析: 解法1:由于数组已经排序,所以可以考虑使用二分查找确定给定数字A的第一个出现的位置m和最后一个出现的位置n,最后m-n+1就是A出现的次数: ...
- O(nlogn)LIS及LCS算法
morestep学长出题,考验我们,第二题裸题但是数据范围令人无奈,考试失利之后,刻意去学习了下优化的算法 一.O(nlogn)的LIS(最长上升子序列) 设当前已经求出的最长上升子序列长度为len. ...
- LCS 算法实现
动态规划算法 #include <iostream> #include <string.h> #include <algorithm> #include <m ...
- Levenshtein Distance + LCS 算法计算两个字符串的相似度
//LD最短编辑路径算法 public static int LevenshteinDistance(string source, string target) { int cell = source ...
随机推荐
- JS高程13.3事件对象的学习笔记
1.事件流 事件流描述的是页面中元素接收事件的顺序.比如你单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,换句话说,在单击按钮的同时,你也单击了按钮的容器元素,甚至还单击了整个页面.那么你到底是 ...
- Java对象、引用、实例
https://blog.csdn.net/zmx729618/article/details/54093075
- (转) Using the latest advancements in AI to predict stock market movements
Using the latest advancements in AI to predict stock market movements 2019-01-13 21:31:18 This blog ...
- vue页面优化中的v-show和v-if使用比较
在页面中使用了v-if做了一个tab框,点击不同的tab框,并加载不同的内容,由于各tab框对应的内容是4到5张统计图,加载的数据量比较大,发现后台请求响应返回的时间很快,在100ms以内,但点击ta ...
- threejs 草场足球运动视角(三)
这次要模拟的场景如下图:就是在绿草地上足球的运动,并且视角会随着足球的运动发生变化,同时整个草地的视角也会旋转. 接下来,我们就对各个元素进行分析: 1,草地 用PlaneGeometry在三维空间里 ...
- loadrunner 参数化-如何从数据库中取数据-连接数据库进行参数化
LoadRunner提供两种参数化取值方式,一种是手动编辑,另一种就是通过连接数据库取值.一般在大型业务并发压力测试时,数据量肯定也都是非常大的,所以手动去编辑就不切实际了,这时用连接数据库的功能就方 ...
- [转]osgconv工具简介
osgconv是一种用来读取3D数据库以及对它们实施一些简单的操作的实用应用程序,同时也被称作 一种专用3D数据库工具. 用osgconv把其他格式的文件转换为OSG所支持的格式 osgconv是一种 ...
- [原]osg模型动画|骨骼动画
参考源码:osg的官方例子:osganimationviewer 首先制作一个带骨骼动画的模型 demo.FBX 这里面我们做了两个骨骼动画:1.open 2.close 下面开始在osg中使用 ...
- MySQL中Decimal类型和Float Double的区别 & BigDecimal与Double使用场景
MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形 ...
- java,桶排序,冒泡排序,快速排序
1.桶排序: 百度百科:桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里.每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排 ...