回溯算法

KMP算法

僤鯓⒐⒋嵵緔 提交于 2020-02-11 23:35:29
简单模式匹配算法 对于一个串中某子串的定位操作称为模式匹配 int i=1,j=1,k=i; //从主串和模式串第一个位置开始遍历 while(i <= s_length && j <= t_length){ if(s[i]==t[j]){//如果相等,则都向后进一位 ++i; ++j; } else{ //如果不相等,则 i 回溯到下一位,j 回溯到模式串第一位,重新依次比较 j=1; i=++k; //或写为i=i-j+2; } } if(j > t_length)cout<<k<<endl; else cout<<"NO"<<endl; KMP算法 简单模式匹配算法需要不断回溯主串和子串,但是KMP算法只需要回溯字串,这就是它更快的原因 原来需要将子串回溯到下标为1,将主串回溯到下一位,KMP算法只需要将子串下标 j 回溯到 next[j] 的位置,所以 求next数组 就是它的核心 出现了几个个问题: 1.next数组存的是什么? 为什么只用将子串下标 j 回溯到 next[j]的位置就能达到我们想要的效果? 2.怎么求next数组。 1.next[j]数组存的是如果主串和子串失配,j要回溯的那个位置 如图,如果按照原来的方法,主串和子串都需要回溯比较,但是我们发现有一些比较其实是可以省略的,观察图中,发现 a. 比较下标前面的子串完全匹配。 b.

LeetCode回溯系列(0)——回溯算法讲解

与世无争的帅哥 提交于 2020-02-08 11:59:07
什么是回溯算法?     回溯法是一种系统搜索问题解空间的方法。为了实现回溯,需要给问题定义一个解空间。说到底它是一种搜索算法。只是这里的搜索是在一个叫做解空间的地方搜索。而往往所谓的dfs,bfs都是在图或者树这种数据结构上的搜索。   根据定义来看,要实现回溯,需要两点: 搜索 解空间 先看什么是解空间   就是形如数组的一个向量[a1,a2,....,an]。这个向量的每个元素都是问题的部分解,只有当这个数组的每一个元素都填满(得到全部解)的时候,才表明这个问题得到了解答。 再看搜索 最简单的就是for循环,上面的向量有n个维度,因此就是n个for循环。 形如: for(求a1位置上的解) for(求a2位置上的解) for(求a3位置上的解) ...... ...... for(求an位置上的解)   但是如果n是100?n是100000?那么如何回溯?当然也可以写n个for循环,但是这样的程序会惨不忍睹。。。而且似乎10000个(不过往往回溯的时间复杂度太大,一般n不会这么大)for循环也很难写出来。。。 因此我们需要一种全新的书写回溯的方法。形如: void backtrack(int i,int n,other parameters) { if( i == n)    {    //get one answer record answer; return; } /

回溯算法3——装箱问题

主宰稳场 提交于 2020-02-04 04:36:58
有n个集装箱要装到两艘船上,每艘船的容载量分别为cl, c2,第i个集装箱的重量为w[i], 同时满足: w[]+w[2)+.+w[n]<=c1+c2; 确定一个最佳的方案把这些集装箱装入这两艘船上。 【分析】 最佳方案的方法:首先将第一艘船尽量装满,再把剩下的装在第二艘船上。第一艘船尽量装满,等价于从n个集装箱选取一一个子集,使得该子集的问题解空间: (x1, x2, x3, . xn),其中,xi为0表示不装在第一艘船上,为1表示在第一艘船上; 约束条件: (1)可行性约束条件: w1xx1+w2x2...ixi.+..+wn * xn<=c1。 (2)最优解约束条件: remain+cw>bestw (remain 表示剩余集装箱重量,cw表示当前已装上的集装箱的重量,bestw 表示当前的最优装载量)。 例如,集装箱的个数为4,重量分别是10、20、35、40,第一艘船的最大装载量是50,则最优装载是将重量为10和40的集装箱装入。首先从第一个集装箱开始,将重量为10的集装箱装入第一艘船, 然后将重量为20的集装箱装入,此时有10+20< -50,然后试探将重量为35的集装箱装入,但是10+20+35>50,所以不能装入35,紧接着试探装入重量为40的集装箱,因为10+20+40>50,所以也不能装入。因此30成为当前的最优装载量。取出重量为20的集装箱(回溯

回溯算法2——填字游戏

为君一笑 提交于 2020-02-03 18:05:47
在3x3的方格中填入数字1~N(N>0)中的某9个数字,每个方格填1个整数,使相邻的两个方格中的整数之和为质数。求满足以上要求的各种数字填法。 【分析】 利用试探法找到问题的解,即从第一一个方格开始, 为当前方格寻找一个合理的整数填入,并在当前位置正确填入后,为下一方格寻找可填入的合理整数。如果不能为当前方格找到一个合理的可填整数,就要回退到前一方格,调整前一方格的填入数。当第9个方格也填入合理的整数后,就找到了一个解,将该解输出,并调整第9个填入的整数,继续寻找下一个解。为了检查当前方格填入整数的合理性,引入二维数组checkMatrix 存放需要合理性检查的相邻方格的序号。 为了找到一个满足要求的9个数的填法,按照某种顺序(如从小到大)每次在当前位置填入一个整数,然后检查当前填入的整数是否能够满足要求。在满足要求的情况下,继续用同样的方法为下一方格填入整数。 如果最近填入的整数不能满足要求,就改变填入的整数。 如果对当前方格试尽所有可能的整数,都不能满足要求,就得回退到前一方格 (回溯),并调整该方格填入的整数。如此重复扩展、检查、调整,直到找到一个满足问题要求的解, 将解输出。 code: #include<stdio.h> #define N 12 int b[N + 1]; int a[10];/*存放方格填入的整数*/ int total = 0;/*共有多少种填法*/

无尽算法之 DFS+回溯算法 暴揍 leetcode.78 子集

删除回忆录丶 提交于 2020-01-28 07:37:14
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 说明:解集不能包含重复的子集。 示例: 输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ] 分析: 例如: 输入 [1,2,3] 如果我们要计算子集 那么, 它的每个元素1, 2, 3 都有两种情况: 选择 和 不选择 , 所以直接递归回溯 注意 不选择的情况注意吧temp list 清空 再加上递归跳出条件 (索引不能越界) 搞定! 题解: class Solution { ArrayList results = new ArrayList ( ) ; public List < List < Integer > > subsets ( int [ ] nums ) { results . add ( new ArrayList ( ) ) ; Arrays . sort ( nums ) ; dfs ( new ArrayList ( ) , nums , 0 ) ; return results ; } public void dfs ( List < Integer > temp , int [ ] nums , int i ) { if ( i >= nums . length ) { return

搜索与回溯算法(三)

≡放荡痞女 提交于 2020-01-28 05:00:19
本节学习要点: 1、 深度优先搜索的基本思想是什么? 2、 深度优选搜索的基本框架(用回溯递归实现) 3、 深度优先搜索算法要点 4、 搜索与回溯练习题二部分试题讲解。 搜索是人工智能中的一种基本方法,也是信息学竞赛选手所必须熟练掌握的一种方法,它最适合于设计基于一组生成规则集的问题求解任务,每个新的状态的生成均可使问题求解更接近于目标状态,搜索路径将由实际选用的生成规则的序列构成。我们在建立一个搜索算法的时候.首要的问题不外乎两个:以什么作为状态?这些状态之间又有什么样的关系?其实.在这样的思考过程中.我们已经不知不觉地将一个具体的问题抽象成了一个图论的模型——树(如图7-l所示)。 状态对应着顶点.状态之间的关系(或者说从一个状态到另一个状态的形成过程即生成规则)对应着边。这样的一棵树就叫做搜索树。初始状态对应着根结点,目标状态对应着目标结点。我们的任务就是找到一条从根结点到目标结点的路径——一个成功的解。搜索算法的实现类似于图或树的遍历,通常可以有两种不同的实现方法:深度优先搜索( DFS——Depth First Search )和宽度优先搜索( BFS——Breadth First Search ). 1 、深度优先搜索的基本思想: 如算法名称那样,深度优先搜索所遵循的搜索策略是尽可能“深”地搜索树。在深度优先搜索中,对于当前发现的结点

数据结构——递归(回溯算法实现八皇后问题)

a 夏天 提交于 2020-01-27 17:32:34
递归——回溯算法 八皇后问题介绍 八皇后问题,是一个古老而著名的问题,是回溯算法的经典案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8x8国际象棋棋盘上拜访8个皇后,使其不能够相互攻击,即:任意两个皇后都不能够处于同一行,同一列,同一斜线上,问共有多少种摆法? 解题思路: 1、第一个皇后先放在第一列上 2、第二个皇后在放在第二行的第一列上,然后判断是否符合条件,如果不符合,放在第二列,第三列。。。 如果符合,那么继续 3、继续第三个皇后,还是从第一列开始,然后第二列。。。当到最后第8个皇后也放在一个不冲突的位时,证明得到了一个正确的解 4、当有一个正确的解后,在栈退回到上一个栈时,回溯开始,最后就会将第一个皇后在第一列中所有解全部得到 5、然后在回头继续将第一个皇后放到第一行的第二列上,继续上面操作 注:我们通过一个一维数组就可以来解出八皇后的所有解,数组下标值可以认为是行,每个下标值对应的数据是在这一行中,皇后所在的列。因为数组下标为0,所以我们将行和列都从0开始 写三个方法: 1、用来放置皇后的方法 2、用来判断当前放置的皇后与已经放置的皇后是否冲突 3、打印方法 代码: package cn . littleworm ; /* 八皇后问题: 任意两个皇后不能够出现在同一行,同一列,同意斜线上 解题思路: 1、第一个皇后先放在第一列上 2

算法第五章作业

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-27 06:25:32
你对回溯算法的理解(2分)   回溯的实质是在问题的解空间进行深度优先搜索。   这句话是我在刚接触到回溯算法时看到的,开始一直很不理解,到现在只能说理解了一些了吧,回溯算法即穷举法,不断地尝试可能的方法,   尝试的过程中根据深度优先原则进行遍历以及回退到上一层的状态,最后通过比较各个方法的结果,从而得到最优解。 请说明“子集和”问题的解空间结构和约束函数(2分)   子集和问题的解空间结构为n层的二叉树,每一层有两个分支,1代表选中,0则为不选。   约束函数:到t层时,若sum的值加上当前节点值大于目标值,则不选当前节点。 请说明在本章学习过程中遇到的问题及结对编程的情况(1分)   结对编程的过程依然非常愉快! 来源: https://www.cnblogs.com/chanchanchan/p/10170075.html

N皇后问题(回溯递归思想)

房东的猫 提交于 2020-01-26 22:53:23
八皇后问题,是一个古老而著名的问题,是 回溯算法 的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即 任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 由此再来发展到N皇后问题 先求其解的个数://回溯算法也就是穷举法 1.每一行放一个皇后 2.放下一行的时候,进行判断:会不会出现同列,会不会出现同一斜线。斜线的判断可以归于斜率判断。 //递归回溯代码如下:#include<iostream> using namespace std; #include<math.h> #define N 16 int n; //皇后个数 int sum = 0; //可行解个数 int x[N]; //标记皇后放置的列数 bool Agree(int k) { int i; for (i = 1; i < k; i++) if (abs(k - i) == abs(x[k] - x[i]) || x[k] == x[i]) return false; return true; } int queen(int t) { if (t > n&& n > 0) //当放置的皇后超过n时,可行解个数加1,此时n必须大于0 sum++; else for (int i = 1; i <= n; i++) { x[t]

39.回溯算法

不问归期 提交于 2020-01-26 18:21:20
回溯法采用 试错 的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的 递归 方法来实现,在反复重复上述的步骤后可能出现两种情况: 找到一个可能存在的正确的答案 在尝试了所有可能的分步方法后宣告该问题没有答案 在最坏的情况下,回溯法会导致一次 复杂度 为 指数时间 的计算。 int[] result = new int[8];//全局或成员变量,下标表示行,值表示queen存储在哪一列 public void cal8queens(int row) { // 调用方式:cal8queens(0); if (row == 8) { // 8个棋子都放置好了,打印结果 printQueens(result); return; // 8行棋子都放好了,已经没法再往下递归了,所以就return } for (int column = 0; column < 8; ++column) { // 每一行都有8中放法 if (isOk(row, column)) { // 有些放法不满足要求 result[row] = column; // 第row行的棋子放到了column列 cal8queens(row+1); //