1. 程式人生 > >復旦研究生歷年機試試題

復旦研究生歷年機試試題

1. (2014)計算兩個字串的編輯距離
問題定義
把兩個字串變成相同的三個基本操作定義如下:
1. 修改一個字元(如把a 變成b)
2. 增加一個字元(如abed 變成abedd)
3. 刪除一個字元(如jackbllog 變成jackblog)
針對於jackbllog 到jackblog 只需要刪除一個或增加一個l 就可以把兩個字串變為相同。把這種操作需要的最小次數定義為兩個字串的編輯距離L。
編寫程式計算指定檔案中字串的距離。輸入兩個長度不超過512 位元組的ASCII 字串,在螢幕上輸出字串的編輯距離。
輸入樣例
Hello world!
Hello wortd!
輸出樣例
1

分析: 和最長公共子串極為相似,具體為

dp[i][j]={dp[i1][j1]str1[i]=str2[j]min{dp[i1][j1]+1dp[i1][j]+1dp[i][j1]+1}str1[i]str2[j]
注: str1[i] != str2[j]時,三種情況的解釋如下:
  1. alter str1[i]、str2[j]
  2. delete str1[i] or add str2[j]
  3. delete str2[j] or add str1[i]

初試化條件為:

dp[0][0]=0,dp[0][j](j[1,m])=j,dp[i][0](i[1,n])=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,找到PM中出現的所有子串的第一個字元在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;
}