朴素 DP(O (n²))
dp[i]表示以i结尾的最大上升子序列长度
太慢了。。
我们可不可以反过来想?
dp[i]表示最长子序列长度为i的最小的末尾元素
比如a = [ 4, 2, 3, 1, 5 ,6 ,3 ]
* 开始时4 dp[1]=4 [4]
* 2加入 dp[1]=2 [2]
* 3 dp[2]=3 (3比2大,可以在末尾加)[2,3]
* 1 dp[1]=1 [1,3]
* 5 dp[3]=5 [1,3,5]
* 6 dp[4]=6 [1,3,5,6]
* 3 dp[3]=3 [1,3,3,6]
我们在遍历过程中在找dp中元素比自己小的然后加进去
比如再加入第2个3时,dp数组是这样的
dp=[1,3,5,6](我们可以发现它是具有单调性的,优化点就在这,进行二分)
我们找到第一个≥3的也就是dp[3]=5
再进行替换dp[3]=3
最后的时间复杂度为O(nlogn)
然后这个优化也可以用来优化LCS(仅限其中一个字符串太长,就比如n<=100,m<=1e6)
这里只写大概思路:
dp[i]为匹配了i对后最靠前的匹配完了的坐标
O(n* l * logm)这个算法叫 Hunt‑Szymanski 算法