給出乙個長為\(n\)的陣列\(a\),與乙個長為\(m\)的陣列\(b\)
求陣列\(a\)與陣列\(b\)的最長公共上公升子串行長度並輸出任意一組方案
\(1\leq n,m\leq 5000\)
這題很有意思
首先對於這類匹配問題,我們一般可以設\(f[i][j]\)表示\(a\)陣列中考慮到\(a_i\)且\(a_i\)必須選,\(b\)陣列中考慮到\(j\)的最長公共上公升子串行的長度
設出方程以後轉移就比較好想了
當\(a[i]=a[j]\)時
\(f[i][j]=max\+1\),其中\(k且\(a[k]
當\(a[i]\neq a[j]\)時
\(f[i][j]=f[i][j-1]\)
想到轉移以後,顯然的思路是直接按照轉移方程寫,即第一層迴圈列舉\(i \ from \ 1...n\),第二層迴圈列舉\(j \ from \ 1...m\)
但這樣我們會發現\(max\)的條件不好維護
樸素的轉移是\(o(n^3)\)的,就是用線段樹優化轉移也是\(o(n^2 \log n)\)的,對於\(n \leq 5000\)的資料來說還是有點卡,更別說線段樹自帶的大常數了
考慮轉換一下列舉順序,即先列舉\(j \ from \ 1...m\),再列舉\(i \ from \ 1...n\)
這樣我們只需要在列舉的過程中順便記錄一下\(max\)就可以在之後\(o(1)\)進行轉移了
但是有乙個問題,之前我們需要的條件判斷是\(k且\(a[k]
第乙個條件還好辦,主要是第二個條件:對於\(i\)不確定的情況下,我們如何確定\(a[i]\)的值呢?
我們會發現,由於是公共子串行,又由於\(a[i]=b[j]\)的時候才能產生貢獻,我們把\(a[i]\)替換為\(b[j]\)就好了
至於求方案,記錄一下更新狀態時是由哪個狀態轉移過來的就行了
#include #include using namespace std;
#define pii pair#define x first
#define y second
const int n = 5e3 + 10;
int n, m;
int a[n], b[n], f[n][n];
pii lst[n][n];
void output(int i, int j)
int main() else
} }int ans = 0, pos = 0;
for (int i = 1; i <= n; ++i)
if (f[i][m] > ans)
ans = f[i][m], pos = i;
printf("%d\n", ans);
output(pos, m);
return 0;
}
《一切都是最好的安排》之感想
你失去的只是無知 把生命的無常變成奇蹟 乙個不經意間在書城發現了這本書,放在非常顯眼的位置,沒有找到自己心亦的專業書,就把這本心靈之書帶回家了。16年發生了太多太多的故事,不管是工作還是生活上的,本書確實是一頓精神大餐,從佛法的方向講訴小的故事,也許心靈雞湯比較多,但在如此快節奏和實現物質的社會,時...
阻止你創業的理由?一切都是浮雲!
事實上真正的成功者,完全會拋開一切客觀的既定的因素,朝著目標勇往直前。創業者們在創業路上少些猶豫,離成功便會越來越近。有些人被陳腐觀念所束縛,也就失去獲取成功的最佳時機,未能成為幸運的寵兒。事實也是,前怕豺狼後怕虎,何來成功。大多數創業者只是一味的徘徊在創業大門外,而不敢邁進去。總被所說的理由所左右...
一切都是最好的安排 軟考總結
2017年11月11日19 30分,從北京回到了機房。閒來無事,寫寫總結吧。考前複習 因為中間接觸了一段時間的angular框架,所以最後留給軟考的複習時間挺少的。最後慌慌張張的就要去考試了。總結出了點小心得 1 想專心複習時就遠離電腦。2 總結知識點時,能畫圖就不要寫字。3 能把知識點組成網很重要...