原创 第一節 搜索算法基礎

搜索算法是利用計算機的高性能來有目的地窮舉一個問題的部分或所有的可能情況,從而求出問題的解的一種方法。搜索過程實際上是根據初始條件和擴展規則構造一棵解

原创 二分查找

int bsearch(int A[], int l, int r,int a) { int m = (l + r) / 2; if (A[m] == a) return m; else if (A[m]

原创 最長上升子序列(LIS)

問題描述:給出一個數列,找出這個數列中最長上升子序列中所包含的個數。最長上升子序列指對於數列an對於任意i小於j,滿足ai小於aj的子序列 很容易能想到一個dp的方法: dp[i]=以i爲末尾的最長上升子序列 但是該方法複雜度爲O(

原创 最長公共子串(後綴數組+LCP)

求兩個串的最長公共子串,我們可以將兩個串中間插入一個兩個串都沒有的字符串起來,然後計算出他的後綴數組(sa)和高度數組(lcp),不在同一串中的sa中相鄰後綴的最長公共前綴(即高度數組的最大值)就是兩個串的最長公共子串。 #include

原创 01揹包,完全揹包,多重揹包(O(V*n))

01揹包 有n種重量和價值分別爲w[i]和v[i]的物品,每種各一個。從這些物品中挑選出總重量不超過W的物品,求所有挑選方案的價值總和最大值。 思路:容易得到該問題的狀態轉移方程爲dp[i][j]=max(dp[i-1][j],dp[i-

原创 最長迴文子串(Manancher算法)

計算迴文子串的方法有很多,比如將該串反轉後拼接在一起利用後綴數組,這裏用一個O(n)的算法 首先這個算法爲了將奇數串和偶數串放一起考慮,在每個字符的之間都加入了一個該字符串不存在的字符,如: aabbaa #a#a##b#b#a#

原创 getMin功能的棧

stack<int> stackData;//存放棧數據 stack<int> stackMin;//存放棧的最小值 void push(int x) { stackData.push(x); if (stackMin.

原创 高度數組(後綴數組伴侶lcp)

利用後綴數組和尺取法求得相鄰兩個後綴數組之間的最長公共前綴,計入lcp數組,這個數組就是高度數組。求整個串從i到j的最長公共前綴就是一個高度數組上的標準的RMQ問題。 int rank[maxn]; void calc_lcp(char*

原创 種子填充(floodfill)

#define clr(a,x) memset(a,x,sizeof a) char a[100][100]; //需要填充的數組a pair<int, int> que[maxn]; //存儲當前的點在數組中的

原创 全排列的求法(DFS)

A爲輸入的一組數 used用來標記A中第i個數是否已經被用過 perm數組用來存放已經生成的排列 DFS(x,n)是新的排列第x位的數 int A[maxn]; bool used[maxn]; int perm[maxn]; bo

原创 後綴數組(倍增法+基數排序思想)

我們只要記錄字符串每個後綴的起始位置,就可以表示字符串的每一個後綴。將這種表示按照後綴的字典序排序,就得到了後綴數組。下面用倍增法求後綴數組,每次計算從i開始,長度爲k的字符串的字典序rank(i,k)利用基數排序的思想,我們已經計算好了

原创 滑動窗口最值(單調隊列)

問題:給定一個數組和滑動窗口的大小,找出所有滑動窗口裏數值的最大值。 解法:利用單調隊列來保存未過期(在w窗口內)的之前的最大值,如果當前值大於該值,就從隊首彈出,直到找到大於當前值得位置,將當前值的位置壓入隊首,如果數據過期,就從隊尾

原创 最長公共子序列(DP)

dp[i][j]表示s串的前i個字符和t串的前j個字符的最長公共子序列 則當s[i]==t[j]時,dp[i+1][j+1]=dp[i][j]+1 當s[i]!=t[j]時,dp[i + 1][j + 1] = max(dp[i][j

原创 AC自動機(trie+KMP)

AC自動機可以在線性時間內匹配多個模式串,算法思路是一個在trie上使用KMP算法 trie的講解和AC自動機算法具體講解(dalao的帖子) http://www.cppblog.com/menjitianya/archive/20

原创 冪取模

可以每乘一次取一次模的方式來求一個數冪的模,時間複雜度爲O(n),但是當n很大時,算法不是很理想,下面用分治的方法來求,其複雜度爲O(logn) int pow_mod(int a, int n, int m) { if (n =