C++程序用于查找给定字符串是否有长度为2或更长的重复子序列
给定一个字符串,找到一个长度至少为两个、在字符串中重复的子序列。子序列元素编号的索引不能处于相同的顺序。
string s = "PNDPNSP"; print("Repeated subsequence of length 2 or more: ", (check(s) ? "Yes" : "No"));
让我们看一下下面的几个例子,以了解这种方法在不同情况下的工作原理 -
示例 1 - str = "PNDPNSP"
Explanation − 这里,答案是true,因为字符串中有一个重复出现的子序列"PN"。
示例 2 - str = "PPND"
解释 - 这里,答案是错误的,因为字符串中没有重复的长度至少为两个的子序列。
示例3 − str = "PPNP"
解释 - 这里,答案是正确的,因为“PP”索引0和1以及“PP”索引1和3存在,并且使用的“PP”在子序列中按顺序具有不同的索引。 (基于 0 的索引)
Brute force Approach
的中文翻译为:暴力破解方法
这种方法将生成长度为 2(最小长度)的所有可能的子序列,并查找我们是否已经看到该子序列与已找到的子序列。如果子序列已经存在,我们返回 true 并终止程序;否则,在完成迭代后,如果我们什么也没找到,则返回 false。
在最坏的情况下,这个子序列可能不存在,我们最终会生成所有可能的结果。
两个长度的子序列并将它们存储起来。因此,假设您对计算的子序列进行哈希处理以实现O(1)的插入和搜索,这将变为O(n^2)。总的子序列也是O(n^2),所以存储空间也是如此。修改后的最长公共子序列(LCS)
LCS 算法找到 2 个字符串中的最长公共子序列。它是一种标准的动态规划方法,使用二维矩阵的迭代方法。时间复杂度为O(n^2)。我们将仅在修改后的方法中搜索给定字符串本身。尽管如此,我们还将检查当前位置的索引是否不相同。
示例
查看下面的 C++ 代码来实现修改后的最长公共子序列算法,该算法有助于我们的方法找到长度为 2 或以上的重复子序列 -
#include <iostream> using namespace std; bool modifiedLongestCommonSubsequence(string s) { int n = s.length(); int dp[n+1][n+1]; for (int i=0; i<=n; i++) fill(dp[i], dp[i]+n+1, 0); for (int i=1; i<=n; i++) { for (int j=1; j<=n; j++) { if (s[i-1]==s[j-1] && i!=j) { dp[i][j] = 1 + dp[i-1][j-1]; } else { dp[i][j] = max(dp[i][j-1], dp[i-1][j]); } } } if(dp[n][n] > 1) return true; return false; } int main() { string str = "PNDPNSP"; cout << "Repeated subsequence of length 2 or more: " << (modifiedLongestCommonSubsequence(str) ? "Yes" : "No"); return 0; }
输出
Repeated subsequence of length 2 or more: Yes
当然,时间和空间复杂度是O(n^2),但是从第一种方法来看,它更加优雅且容易产生O(1)的哈希。
改进的解决方案
在这种方法中,我们将尝试在之前的方法基础上进行一些观察。
观察1 − 如果一个字符出现超过两次,答案总是真的。让我们看看为什么?
示例 - 在字符串 str = "AVHJFBABVNHFA" 中,我们在位置 0、6 和 12 中有 "AAA"。所以 我们可以将索引为0和6的"AA"作为一个子序列,以及将索引为6和12的"AA"作为一个子序列 作为另一个。
观察 2 - 如果一个字符只重复一次,它不能对我们的结果做出贡献 子序列,因为它只会在最多一个子序列中可用。它将无法工作 因为我们需要至少两个子序列。所以我们可以删除或忽略所有字符 发生在同一时间。
观察3 − 如果一个字符串是回文,并且前两个观察都适用,那么答案是 除非字符串长度为奇数,否则始终为 false。让我们看看为什么?
示例 - 字符串 str = "PNDDNP"
解释 - 现在,字符不按顺序排列,因此我们永远无法找到 子序列具有相同的顺序,因此不可能。
示例
根据上述所有三个观察结果,我们得出的结论是,如果我们删除字符串中出现一次的所有字符,然后检查某个字符是否出现两次以上或者字符串是否不是回文,那么我们的答案是正确的。让我们看看改进后的解决方案在 C++ 中的实现 -
#include <iostream> using namespace std; bool isPalindrome(string s) { for(int i=0;i<s.size()/2;i++) { if(s[i]!=s[s.size()-1-i]) { return false; } } return true; } bool check(string s) { int hash[26] = {0}; for (int i = 0; i < s.size(); i++) { hash[s[i]-'a']++; if (hash[s[i]-'a'] > 2) { return true; } } int k = 0; string mstr = ""; for (int i = 0; i < s.size(); i++) { if (hash[s[i]-'a'] > 1) { mstr[k++] = s[i]; } } if (isPalindrome(mstr)) { return false; } return true; } int main() { string s = "PNDPNSP"; cout << "Repeated subsequence of length 2 or more: " << (check(s) ? "Yes" : "No"); return 0; }
输出
Repeated subsequence of length 2 or more: Yes
结论
我们得出结论,使用观察和哈希是解决这个问题的最佳方法。时间复杂度为O(n)。空间复杂度也是O(n)的顺序,创建一个新的字符串和常数26个字符的哈希。
以上是C++程序用于查找给定字符串是否有长度为2或更长的重复子序列的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

关闭iPhone版“查找”后会发生什么?“查找我的iPhone”可帮助您定位丢失或被盗的设备。启用后,“查找我的iPhone”可让您在地图上跟踪设备的位置、播放声音并帮助您找回设备。“查找”还包括一个激活锁,可防止任何人使用您的iPhone。当您关闭“查找我的iPhone”时,您将失去所有这些功能,这可能会使恢复丢失的Apple设备变得困难。虽然“查找我的iPhone”非常有用,但当您想出售、捐赠、以旧换新手机或想要将其送去更换电池或任何其他服务时,您应该禁用它。这样做将确保没有人可以访问有关您

Apple的“查找”应用程序允许您定位您的iPhone或其他设备,以防止丢失或遗忘。虽然“查找”是一个有用的工具来追踪设备,但如果您关注隐私问题、不想耗尽电池或其他原因,您可能希望禁用它。幸运的是,有几种方法可以关闭iPhone上的“查找”,我们将在这篇文章中解释所有这些方法。如何在iPhone上关闭“查找”[4种方法]您可以通过四种方式关闭iPhone的“查找”。如果您使用方法1关闭“查找”,则可以从要禁用它的设备上执行此操作。要继续执行方法2、3和4,要关闭“查找”的iPhone应关闭电源或

使用C#中的Array.IndexOf函数查找数组中某个元素的索引在C#程序中,当我们需要查找数组中某个元素的索引时,可以使用Array.IndexOf函数。Array.IndexOf函数会在指定的数组范围内查找指定的元素,并返回其第一次出现的索引。如果未找到该元素,则返回-1。下面是一段示例代码,演示了如何使用Array.IndexOf函数查找数组中某个元

硬盘序列号和MAC地址是电脑硬件中重要的标识符,它们在管理和维护电脑系统时非常有用。本文将介绍如何查找硬盘序列号和MAC地址。一、查找硬盘序列号硬盘序列号是硬盘制造商为了识别和追踪硬盘的唯一标识符。在不同的操作系统中,查找硬盘序列号的方法略有不同。Windows系统:打开命令提示符(在开始菜单中搜索“cmd”),然后输入以下命令并按回车键:wmicdisk

PHP中的glob()函数用于查找文件或目录,是一种强大的文件操作函数。它可以根据指定的模式匹配,返回文件或目录的路径。glob()函数的语法如下:glob(pattern,flags)其中,pattern表示要匹配的模式字符串,可以是一个通配符表达式,如*.txt(匹配以.txt结尾的文件),或者是具体的文件路径。flags是一个可选参数,用于控制函数

双曲函数是使用双曲线而不是圆定义的,与普通三角函数相当。它从提供的弧度角返回双曲正弦函数中的比率参数。但要做相反的事,或者换句话说。如果我们想根据双曲正弦值计算角度,我们需要像双曲反正弦运算一样的反双曲三角运算。本课程将演示如何使用C++中的双曲反正弦(asinh)函数,使用双曲正弦值(以弧度为单位)计算角度。双曲反正弦运算遵循以下公式-$$\mathrm{sinh^{-1}x\:=\:In(x\:+\:\sqrt{x^2\:+\:1})},其中\:In\:是\:自然对数\:(log_e\:k)

映射是C++中的一种特殊类型的容器,其中每个元素都是一对两个值,即键值和映射值。键值用于索引每个项目,映射值是与键关联的值。无论映射值是否唯一,键始终是唯一的。要在C++中打印映射元素,我们必须使用迭代器。一组项目中的一个元素由迭代器对象指示。迭代器主要与数组和其他类型的容器(例如向量)一起使用,并且它们具有一组特定的操作,可用于识别特定范围内的特定元素。可以增加或减少迭代器来引用范围或容器中存在的不同元素。迭代器指向范围内特定元素的内存位置。使用迭代器在C++中打印地图首先,我们看一下如何定义

rename函数将文件或目录从旧名称更改为新名称。此操作类似于移动操作。因此,我们也可以使用此rename函数来移动文件。此函数存在于stdio.h库头文件中。rename函数的语法如下:intrename(constchar*oldname,constchar*newname);rename()函数的功能它接受两个参数。一个是oldname,另一个是newname。这两个参数都是指向常量字符的指针,用于定义文件的旧名称和新名称。如果文件重命名成功,则返回零;否则,返回非零整数。在重命名操作期间
