最长重复子串—后缀数组

2024-06-18 13:18

本文主要是介绍最长重复子串—后缀数组,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

知识点:
1. sort 使用时得注明:using namespace std;   或直接打 std::sort()  还得加上  #include <algorithm>
2. qort是qsort的升级版,如果能用sort尽量用sort,使用也比较简单,不像qsort还得自己去写 cmp 函数,
只要注明  使用的库函数就可以使用,参数只有两个(如果是普通用法)头指针和尾指针; 


3. 默认sort排序后是升序,如果想让他降序排列,可以使用自己编的cmp函数


bool compare(int a,int b){
 return a>b; //降序排列,如果改为return a<b,则为升序
}
sort(*a,*b,cmp);


4. compare 函数中对于double需要特别注意返回值的问题,
显然cmp返回的是一个整型,所以避免double返回小数而被丢失。


int cmp( const void *a , const void *b ){
return *(double *)a > *(double *)b ? 1 : -1;

}


分析:要求输出它及其首字符的位置。 例如字符串yyabcdabjcabceg,输出结果应该是abc和3。

  1.可以将上面字符串分解为,后缀数组形式。
substrs[0] =yyabcdabjcabceg;
substrs[1] =yabcdabjcabceg;
substrs[2] =abcdabjcabceg;
substrs[3] =bcdabjcabceg;
substrs[4] =cdabjcabceg;
substrs[5] =dabjcabceg;
substrs[6] =abjcabceg;
substrs[7] =bjcabceg;
substrs[8] =jcabceg;
substrs[9] =cabceg;
substrs[10]=abceg;
substrs[11]=bceg;
substrs[12]=ceg;
substrs[13]=eg;
substrs[14]=g;

  2.对这些字符串按照字典顺序排序,

  3.然后比较相邻字符串的前驱,找到最长的匹配项。


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>using namespace std;pair<int, string> fun(const string &str)
{vector<string> substrs;int maxcount = 1;unsigned int count = 0;string substr;int i, len = str.length();for (i = 0; i < len; i++)   // 得到所有的后缀子串{// basic_string substr(size_type pos = 0,size_type n = npos) const;// 从pos开始,截取n个字符组成的字符串。substrs.push_back(str.substr(i, len-i));}// 后缀树排序sort(substrs.begin(), substrs.end());// 比较相邻两个字符串公共序列string str1;string str2;vector<string>::iterator iter;for(iter = substrs.begin(); iter != substrs.end()-1; ){count = 0;str1 = *iter++;str2 = *iter;while(	count < str1.length() &&  count < str2.length()  &&  (str1.at(count) == str2.at(count))	)count++;if(count > maxcount){maxcount = count;substr = str1.substr(0, maxcount);}}substrs.clear();return make_pair(maxcount,substr);
}int main()
{string str;pair<int, string> rs;while (cin >> str){rs = fun(str);cout << rs.second << ':' << rs.first << endl;}return 0;
}

下面是另一种解题思路:
时间复杂度比上面介绍的要高,但是空间复杂度为O(1).时间换空间。
思路:对源字符串所有后缀的所有子串,从每一个后缀的最长子串开始,
分别从前向和后向开始在源字符串中查找匹配的子串,
若两次查找位置不一致则说明存在重复的长度最长的字串,并返回前向查找时的位置。
e.g. string = “abcedfghiabckl‘,当使用子串”abc“在源字符串中分别前向和后向匹配时,

找到的位置分别为pos1=0, pos2 = 9.

#include <iostream>
#include <string>
using namespace std;
int main()
{string str,tep;cin>>str;cout<<"length=="<<str.length()<<endl;for (int i = str.length()-1; i>=1; i--){for (int j = 0; j < str.length(); j++){// 如果没有这句的约束,那么结果错误。// 这句话使得每次得到的tep的长度是i,即满足从大到小取字符串。if (j + i <= str.length()){size_t t = 0;size_t num = 0;tep = str.substr(j, i); // 从大到小取字串。i是截取的字符串的长度,先截取最长的,再截取次长的t = str.find(tep);		// 正序查找num = str.rfind(tep);	// 逆序查找// 如果两次查找的位置不一样,说明存在重复字串。if (t != num)			// 满足条件就输出,因为是从最长的字符串开始截取。{cout<<tep<<" "<<t<<endl;return 0;}}}}return 0;
}

这篇关于最长重复子串—后缀数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072100

相关文章

LeetCode--220 存在重复元素 III

题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 示例 示例 1:输入: nums = [1,2,3,1], k = 3, t = 0输出: true示例 2:输入: nums = [1,0,1,1], k = 1, t = 2输出: true示例

LeetCode--217 存在重复元素

题目 给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 示例 1:输入: [1,2,3,1]输出: true示例 2:输入: [1,2,3,4]输出: false示例 3:输入: [1,1,1,3,3,4,3,2,4,2]输出: true class Solution {p

axios全局封装AbortController取消重复请求

为什么? 问题:为什么axios要配置AbortController?防抖节流不行吗? 分析: 防抖节流本质上是用延时器来操作请求的。防抖是判断延时器是否存在,如果存在,清除延时器,重新开启一个延时器,只执行最后一次请求。节流呢,是判断延时器是否存在,如果存在,直接return掉,直到执行完这个延时器。事实上,这些体验感都不算友好,因为对于用户来说,得等一些时间,尤其是首次请求,不是那么流畅

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

IOS 数组去重的几种方式

本来只知道NSSet和KeyValues的。今天又新学了几种方式 还有就是和同事学的一种方式 外层循环从0开始遍历,内层从最后一个元素开始遍历 for(int i=0;i<index;i++){  for(int j=index-1;j>i;j-- ){ } }

Java基础(二)——数组,方法,方法重载

个人简介 👀个人主页: 前端杂货铺 ⚡开源项目: rich-vue3 (基于 Vue3 + TS + Pinia + Element Plus + Spring全家桶 + MySQL) 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步至千里,积小流成江海 🥇推荐学习:🍖开源 rich-vue3 🍍前端面试

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符。然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string

poj 3294(Life Forms) 2分+ 后缀数组

我曾用字符串hash写,但是超时了。只能用后最数组了。大致思路:用不同的符号吧字符串连接起来,构建后缀数组,然后2分答案,依次扫描后缀数组,看是否瞒住条件。 VIEW CODE #include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<cstring>#include<cassert>#

C语言函数参数--数组长度

int read_column_numbers(int columns[], int max){} 在函数声明的数组参数中,并未指定数组的长度。这种格式是OK的,因为无论调用函数的程序传递给它的数组参数的长度是多少,这个函数都将照收不误。 这是一个伟大的特性,它允许单个函数操纵任意长度的一维数组。 这个特性不利的一面是函数没法知道该数组的长度。如果确实需要数组的长度,它的值必须作为一个单独的

从JavaScript 数组去重看兼容性问题,及性能优化(摘自玉伯博客)

缘由 JavaScript 数组去重经常出现在前端招聘的笔试题里,比如: 有数组 var arr = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0],请用 JavaScript 实现去重函数 unqiue,使得 unique(arr) 返回 ['a', 'b', 'c', '1', 0, 1, ''] 作为笔试题,考点有二: 正确。别小看这个考点