PART 1
分治递归算法:大问题可分解成小问题,大小问题具有相似性,递归要有边界条件,然后再合并
递归常见问题:求斐波拉数列,手写全排列
#include
using namespace std;
int a[4]={0,1,2,3};
void permutation(int a[],int k,int n){
if(k
swap(a[i],a[k]);
permutation(a,k+1,n);
swap(a[i],a[k]);
}
}
else{
for(int i=1;i<=n;i++)
cout< cout<
}
int main(){
permutation(a,1,3);
return 0;
}
复杂度递推式:当n=1,T(n)=O(1);当n>1,T(n)=kT(n/m)+f(n)
复杂度求解法:代换法,递归树法,主方法
代换法:猜测解的形式,通过数学归纳法找出使解真正有效的常数
迭代法:模拟该递归关系执行过程,从而计算时间
直接展开(代数法algebraic),就是把递推一直推到仅含N与初始条件(首选!)
递归树(几何法geometrical),画出该递归关系式的递归树,树中每个节点都代表递归函数调用集合中的一个子问题的代价,每一层的代价相加得到一个每层代价的集合,层代价相加得到递归的总代价
主方法:略,我才不记那么无聊的公式
PART 2
动态规划算法:分治法类似,其基本思想也是将待求解问题分解成若干个子问题,而DP会,而且DP一定会利用已计算的状态
注意与分治的区别:分治递归当中子问题没有交叉,不会共享底层子问题,自顶向下,不一定会记录已计算的状态
步骤:共四步
找出最优解的性质,并刻划其结构特征(寻找最优解的子问题结构)
递归地定义最优值(根据子问题结构建立问题的递归解式求解最优值)
以底向上的方式计算出最优值(动态规划思想)
根据计算最优值时得到的信息,构造最优解
常见问题:递推式化通项式构造矩阵快速幂,背包问题,区间合并
PART 3
查重:
方案一:S=相同字数/总字数,方案二:S=相同模块字数/总字数
选择较优的方案二,模块表示用HASH
思路:把两篇文档中一定长度的语句或者是语句段映射成字母之后,那么两个文档就对应成了X序列和Y序列两个字符序列,现在问题就是找出X和Y的有多少个字母是相同的,然后代入公式求出查重率,换句话说就是最长公共子序列,注意子序列可以是不连续的,如{1,2,3}与{1,3,4}的最长公共子序列是{1,3}
思路:dp[i][j]=c[i-1][j-1]+1,if(xi=yj),dp=max{c[i][j-1]],c[i-1][j]},if(xi!=yj)
改进:若有连续的序列相同,权重增加!例如有{xi,xj,xk}={yr,ys,yt},其中ijk,rst是连续的,那么相同模块字数是3*(len(xi)+len(xj)+len(xk))
思路:时间N*M,空间开两个同A数组的长度的数组,对每个xi,都与每一个yj匹配一次,共N轮,每轮M次比较每次比较更新数组dp[i]=0,if(xi!=yj);dp[i]=dp[i-1]+1,if(xi==yj),每轮比较完记录DP中的最大值为ANS[]表示以本轮A数组的那个字符为右界的最长连续序列长度,最后用ANS[]来加权即可
另有类似题目:最长上升子序列,最长公共上升子序列