復旦研究生歷年機試試題
1. (2014)計算兩個字串的編輯距離
問題定義
把兩個字串變成相同的三個基本操作定義如下:
1. 修改一個字元(如把a 變成b)
2. 增加一個字元(如abed 變成abedd)
3. 刪除一個字元(如jackbllog 變成jackblog)
針對於jackbllog 到jackblog 只需要刪除一個或增加一個l 就可以把兩個字串變為相同。把這種操作需要的最小次數定義為兩個字串的編輯距離L。
編寫程式計算指定檔案中字串的距離。輸入兩個長度不超過512 位元組的ASCII 字串,在螢幕上輸出字串的編輯距離。
輸入樣例
Hello world!
Hello wortd!
輸出樣例
1
分析: 和最長公共子串極為相似,具體為
注: str1[i] != str2[j]時,三種情況的解釋如下:
- alter str1[i]、str2[j]
- delete str1[i] or add str2[j]
- delete str2[j] or add str1[i]
初試化條件為:
2 . (2015)正方形個數
給出長方形的長和寬,每次從長方形裡撕去最大的正方形,輸出最後能得到多少正方形
void square_cnt(int l, int w) {
int cnt = 0;
while (l > w) {
l -= w;
cnt++;
if (l < w) swap(l,w);
}
printf("%d", cnt + 1); //l=w(+1)
}
3 . (2015)優先順序佇列的實現
ADD N P:往佇列里加入id為N的優先順序為P的任務
NEXT:輸出下一個最高優先順序的任務的id,如果優先順序相同輸出id小的任務,若佇列中沒有任務輸出-1
REMOVE N:移除id為N的任務
COUNT:輸出佇列中的任務數量
分析: 剛學會了priority_queue就拿來用用,但是有個缺陷就是REMOVE時要O(pq.size())的複雜度,不過因為不清楚具體資料量,也不會其它方法,就先這樣啦,核心程式碼如下:
struct process{
int id;
int p;
process(int a = 0, int b = 0) :id(a), p(b) {} //init
};
struct cmp {
bool operator() (process p1, process p2) {
if (p1.p == p2.p) {
return p1.id > p2.id; //優先順序相同則id小的在前
}
return p1.p < p2.p; //優先順序大的在前
}
};
//priority_queue<int> qi; //後兩個引數預設,優先佇列就是大頂堆,隊頭元素最大
priority_queue<process, vector<process>, cmp> pq;
4 . (2016) Huffman編碼長度
給定一個字串,求哈夫曼編碼的長度
核心步驟如下:
1. f1陣列記錄字元出現頻度(hash, 用於建樹),然後排序(升序),並設定對應的level陣列(初始為0,用於最後的編碼長度計算)以及f2(cnt統計個數)陣列(合併時的新結點陣列, 升序排列)
2. 從f1和f2中取得最小的兩個結點(最多從4個結點中選擇), 記cnt1(-1)和cnt2(-1)為當前指示下標, 從f1中取得幾個結點, cnt1就加幾, 然後level[0~cnt1]增1, 合併的新結點進入f2,直到f1中結點已遍歷完且f1僅剩一個結點未處理
3. 對level[i]*f1[i] (0~n-1)求和,即為最終Huffman編碼長度
5 . (2014) Hanoi塔
把A 柱上的n 個金片,搬動到C 柱(中間可以使用B 柱),使得搬動的次數最少。輸入金片的個數n(1<=n<=64),輸出總搬動次數,以及最後100 次搬動。如果搬動次數小於等於100 則全部輸出;每個搬動佔一行,加上這是第幾次搬動的數字和”:”,格式見示例。
輸入樣例
2
輸出樣例
3
1:A->B
2:A->C
3:B->C
分析: 不是很明白。。。先貼下非遞迴的連結,以後抽時間補充
http://blog.sina.com.cn/s/blog_48e3f9cd01000474.html
6 . (2013) 字串匹配
對於主串M和模式串P,找到P在M中出現的所有子串的第一個字元在P中的位置。P中第一個字元所在的位置為0。首行
的數字表示有多少組字串。
[輸入及示例]
2
ababababa
ababa
aaa
aa
[輸出及示例]
0 2 4
0 1
(相鄰位置之間用一個空格隔開)
#include <cstdio>
#include <iostream>
#include <string> //string
using namespace std;
void Solve(string m, string p) {
string m1;
int pos = m.find(p);
int len = m.size();
int pos1;
printf("%d", pos);
//原字串上擷取子串時用另一個變數儲存
while (len - pos - 1 >= p.size()) {
m1 = m.substr(pos + 1, len - pos - 1);
pos1 = m1.find(p);
if (pos1 != string::npos) {
pos += (pos1 + 1);
printf(" %d", pos);
}
else break;
}
printf("\n");
}
int main() {
string m, p;
int n;
scanf("%d", &n);
while (n--) {
cin >> m >> p;
Solve(m, p); //至少匹配一個
}
return 0;
}