左神算法进阶班1_1添加最少字符得到原字符N次

Problem:
  给定一个字符串str1,只能往str1的后面添加字符变成str2。

  要求1:str2必须包含两个str1,两个str1可以有重合,但是不能以同一个位置开头。

  要求2:str2尽量短最终返回str2

  举例:

    str1 = 123,str2 = 123123 时,包含两个str1,且不以相同位置开头,且str2最短。

    str1 = 123123,str2 = 123123123 时,包含两个str1,且不以相同位置开头,且str2最短。

    str1 = 111,str2 = 1111 时,包含两个str1,且不以相同位置开头,且str2最短。

Solution:
  使用KMP算法;

  求最后一个字符的后一个空位的最长相同前后缀长度, 然后将字符前面不属于相同部分添加N次就行

Code:

  

 1 #pragma once
 2 #include <iostream>
 3 #include <vector>
 4 #include <string>
 5
 6 using namespace std;
 7
 8 void getIndex(int*& index, string str)
 9 {
10     for (int i = 0, p = 0; i <= str.length(); ++i)
11     {
12         if (i == 0)
13             index[i] = -1;
14         else if (i == 1)
15             index[i] = 0;
16         else
17         {
18             if (str[i - 1] == str[p])
19                 index[i] = ++p;
20             else if (p > 0)
21                 p = index[p];
22             else
23                 index[i] = 0;
24         }
25     }
26 }
27
28 string addStr(string str, int N)
29 {
30     string res = str;
31     int* index = new int[str.size() + 1];
32     getIndex(index, str);//获取最长前后缀角标
33
34     int L = str.length() - index[str.length()];//最后一个位置的前后缀长度
35     for (int i = 1; i < N; ++i)
36     {
37         for (int j = 0; j < L; ++j)
38             res += str[j];
39     }
40     delete[] index;
41     return res;
42 }
43
44
45 void Test()
46 {
47     string str;
48     str = "abcabc";
49     cout << addStr(str, 3) << endl;
50
51     str = "12345";
52     cout << addStr(str, 2) << endl;
53 }

原文地址:https://www.cnblogs.com/zzw1024/p/11029620.html

时间: 2024-07-31 22:32:37

左神算法进阶班1_1添加最少字符得到原字符N次的相关文章

左神算法进阶班1_5BFPRT算法

在无序数组中找到第k大的数1)分组,每N个数一组,(一般5个一组)2)每组分别进行排序,组间不排序3)将每个组的中位数拿出来,若偶数,则拿上 / 下中位数, 成立一个一个新数组.4)新数组递归调用BFPRT,则拿到整体的中位数num5)以num来划分整体数组,小于在左,大于在右边,使用[荷兰国旗方法]6)然后根据左右数组的规模,来确定进一步选择左右哪一部分:7)然后选择好后,继续 一:背景介绍在一大堆数中求其前k大或前k小的问题,简称TOP - K问题.而目前解决TOP - K问题最有效的算法即

左神算法进阶班3_1构造数组的MaxTree

题目 一个数组的MaxTree定义: 数组必须没有重复元素 MaxTree是一棵二叉树,数组的每一个值对应一个二叉树节点 包括MaxTree树在内且在其中的每一棵子树上,值最大的节点都是树的头 给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的函数,要求如果数组长度为N,则时间负责度为O(N).额外空间负责度为O(N). 实现思路 将数组按照大根堆进行排序 然后直接按照大根堆进行构造一颗二叉树即可. 使用单调栈 通过使用单调栈,将数组中中所有数的左右比他大的数记录下来 当某个数

左神算法进阶班5_1求二叉树中最大搜索子树大小

[题目] 给定一棵二叉树的头节点head,请返回最大搜索二叉子树的大小 [题解] 简化问题,想到该问题的解答应该有几种情形 第一种可能: 最大搜索二叉子树在head的左子树 第二种可能: 最大搜索二叉子树在head的右子树 第三种可能: 最大搜索二叉子树为自己:利用左子树的最大值与右子树的最小值 递归左子树,再递归右子树 信息1:左子树中最大搜索二叉树的大小 信息2:右子树中最大搜索二叉树的大小 信息3:左子树最大搜索二叉树的头结点 信息4:右子树最大搜索二叉树的头结点 信息5:左子树上的最大值

左神算法进阶班5_3求公司的最大活跃度

[题目] 一个公司的上下节关系是一棵多叉树,这个公司要举办晚会,你作为组织者已经摸清了大家的心理: 一个员工的直接上级如果到场,这个员工肯定不会来. 每个员工都有一个活跃度的值,决定谁来你会给这个员工发邀请函,怎么让舞会的气氛最活跃? 返回最大的活跃值. 举例: 给定一个矩阵来表述这种关系 matrix = { 1,6 1,5 1,4 } 这个矩阵的含义是: matrix[0] = { 1 , 6 },表示0这个员工的直接上级为1, 0这个员工自己的活跃度为6 matrix[1] = { 1 ,

左神算法进阶班6_1LFU缓存实现

[题目] LFU也是一个著名的缓存算法,自行了解之后实现LFU中的set 和 get 要求:两个方法的时间复杂度都为O(1) [题解] LFU算法与LRU算法很像 但LRU是最新使用的排在使用频率最前面,也就是LRU是通过使用时间进行排序, 使用时间越新,其使用频率越高,而使用时间越久,其使用频率越低,即当空间满时,被删除的概率最大 而LFU是根据使用次数来算使用频率的,使用次数越多,其使用频率越高,使用次数越少,使用频率越低,当空间满时越容易被删除 同样,使用hash_map表和双向链表进行存

左神算法基础班3_13深度拷贝含有随机指针的链表

Problem: 复制含有随机指针节点的链表 [题目] 一种特殊的链表节点类描述如下: public class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; } } Node类中的value是节点值,next指针和正常单链表中next指针的意义 一 样,都指向下一个节点,rand指针是Node类中新增的指针,这个指 针可 能指向链表中

左神算法书籍《程序员代码面试指南》——2_07将单向链表按某值划分成左边小、中间相等、右边大的形式

Problem:[题目] 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个整数pivot. 实现一个调整链表的函数,将链表调整为左部分都是值小于 pivot的节点, 中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点. 除这个要求外,对调整后的节点顺序没有更多的要求. 例如:链表9->0->4->5->1,pivot = 3. 调整后链表可以是1->0->4->9->5, 可以是0->1->9->5-&g

左神算法第八节课:介绍递归和动态规划(汉诺塔问题;打印字符串的全部子序列含空;打印字符串的全排列,无重复排列;母牛数量;递归栈;数组的最小路径和;数组累加和问题,一定条件下最大值问题(01背包))

暴力递归: 1,把问题转化为规模缩小了的同类问题的子问题 2,有明确的不需要继续进行递归的条件(base case) 3,有当得到了子问题的结果之后的决策过程 4,不记录每一个子问题的解 动态规划 1,从暴力递归中来 2,将每一个子问题的解记录下来,避免重复计算 3,把暴力递归的过程,抽象成了状态表达 4,并且存在化简状态表达,使其更加简洁的可能 一:递归 1. 汉诺塔问题 汉诺塔问题(不能大压小,只能小压大),打印n层汉诺塔从最左边移动到最右边的全部过程. 左中右另称为 from.to.hel

【左神算法课】子数组最大差值小于某阈值,求满足条件的子数组个数

题目描述: 解法思路: 本题其实是滑动窗口的变形.主体思路为: 1.从第一个元素开始依次向后遍历,同时维护两个窗口(由于要同时操作窗口的头部和尾部,故采用双端队列): 最大值窗口(递减),头部永远存最大值 最小值窗口(递增),头部永远存最小值 2.比较两个窗口的头部元素差值,若差值大于阈值,即可跳出内循环. 3.跳出内循环后,检查头部元素是否过期,若过期,则清除. 复杂度: 时间复杂度:O(n),注意虽然是两层循环,但元素只从滑动窗口尾部进,从头部清除,只是顺序扫描了一遍. 空间复杂度:O(n)