2013級資料結構第三次上機解題報告

2021-06-21 16:57:51 字數 3953 閱讀 4015

鑑於是上學期的陳題,沒什麼過多可以說的,具體內容請查詢「角谷猜想」。

此外,原本想考察乙個叫「阿克曼函式」的遞迴函式,但是由於該函式在時間與數值上的增長率都十分迅猛,因此沒有設題,有興趣練習一下的同學可以自行查閱並練習一下。

//by trashlhc

#includeusing namespace std;

int cube(int n)

int main()

return 0;

}

//by wjfwzzc

//non-recursive version

#include#include#include#includeusing namespace std;

stack> s;

int main()

int num=0;

for(; isdigit(str[i]); ++i)

num=num*10+str[i]-'0';

if(num==0)

++num;

if(str[i]=='(')

while(num--)

ans+=str[i];

}while(!s.empty())

cout<

其實對一些同學用string類自帶的庫過了這道題表示不明覺厲= =

後來查了一下,c++中的string::find()函式似乎是最樸素的bf演算法加上了隨機化演算法的……所以其平均時間複雜度會比o(m*n)稍稍少那麼一些。並且在小資料上kmp的優勢體現不出來,而這道題的資料又很大程度上是隨機生成的……

嘛,不過還是提供kmp的演算法,畢竟是乙個十分重要的東西。而且從兩種方法的ac耗時上可以看出,kmp還是很有優勢的。

不多說,進入解題分析。

這道題中的萬用字元是乙個神奇的東西,它能匹配任意數量的一段連續字元(就算數目為0也是可以的,很多同學都跪在了這個上面)由於這一附加萬用字元,導致的結果就是要麼我們對kmp演算法進行大改,要麼就要對模式串進行一定處理。大改kmp當年某渣在上機的時候因為技術太弱沒能寫出來(這一年也沒能寫出來……),於是在這裡提供修改模式串的版本。

大致的思路就是以萬用字元為分隔符,將整個模式串分成不同小段的子串。每乙個子串與待匹配串進行一次kmp,得到每一段在文中的位置。如果匹配上了的話,所有匹配的位置將會是乙個公升序的序列,反之一旦這個位置序列的任意位置出現非公升序的情況,則模式串與待匹配串不匹配。

這裡有同學要問了,那如果某乙個子串在帶匹配串中出現了多次呢?由於演算法是從左到右掃瞄待匹配串的,因此只需要匹配第乙個位置就可以了。這個具體的證明大家可以試著推一推,在這裡不再贅述。

//by trashlhc

//專門重寫了乙份kmp,表示某渣當年上資料結構的時候kmp寫得實在是太不優雅了……

#include#include#include#include#define maxsize 9998

#define maxl 100

#define maxn 101

using namespace std;

void getnextval(char t,int nextval)

//稍稍改寫了一點的kmp,由於基於萬用字元對模式串進行了分解,因此這裡每一段進行匹配時,其起始匹配位置不一定為0,而是startpos。

int placeres[maxn]; //placeres用於儲存每一模式子串對應的匹配位置。

char s[maxsize],t[maxsize],splitres[maxn][maxl];

//s為模式串,t為待匹配串,splitres用於儲存s串分解後的模式子串組

void init()

//init函式用於初始化所有的字串,及placeres陣列。

void reshape()box;

typedef struct

qutype;

void print(qutype qu,int front,int number)

while(k!=0);

k=0;

while(k>length>>width)

if(map[i][j]=='z')//獲取重點位置

} printf("where?!\n");//終點不存在或無法到達終點

}}

首先……那個神馬神馬數是個神馬東西?

嘛,暫且不管那個,先看看遞迴模式:

假設現在排隊的人有x個拿著五西斯,y個人拿著十西斯

我們可以很輕易地知道兩個結論:

①    若x②    若y=0,那麼thor一定可以找開錢,而且由於題目描述,這樣只會有一種排隊方式。

除了上面兩種情況外,最普通的情況——x>y的情況下,現在隊中有x+y個人,對於第x+y個人,有兩種可能:他拿著十西斯,他拿著五西斯。

假設這x+y個人有f(x,y)中排隊方式,於是又有了兩個結論:

①    若第x+y個人拿著五西斯,那麼在這種情況下他前面x+y-1個人中有x-1個人拿著五西斯,y個人拿著十西斯,於是這種情況下排隊方式有f(x-1,y)種。

②    若第x+y個人拿著十西斯,那麼在這種情況下他前面x+y-1個人中有x個人拿著五西斯,y-1個人拿著十西斯,於是這種情況下排隊方式有f(x,y-1)種。

於是遞迴式得到:

str+=str; //string類過載了加法運算子

}cout

using namespace std;

typedef char elemtype;

typedef struct

sqstring;

void strassign(sqstring &s,char cstr)

void insstr(sqstring &s1,int i,sqstring s2)

if(manipulate=="del")

if(manipulate=="copy")

insstr(str,str.length,str);

}dispstr(str);

}本題再一次證明了學習英語的重要性= =

a line containing a period follows the lasttest case.

上面這句話的意思是輸入資料以包含點號的一行結束。

某渣的思路是不斷地從頭開始擷取不同長度的子串,看這個串是否可以通過自我重複得到完整的字串。由於長度是從小到大,從1到字串長度的一半依次選擇,因此第一次出現滿足條件的字串必然長度最短,其重複次數也必然是最多的。

但是——

正解非以上,在字串長度較大的時候上述演算法會跪掉= =

那麼正解究竟是什麼呢?

參考標準**解決好了~

//by trashlhc

//folk version

#include#include#includeusing namespace std;

int main()

}

//official version

#include #include #include using namespace std;

const intn=1000010;

int len,nextt[n];

char str[n];

int get_next()

{ nextt[0]=0;

for(int i=1;i

第三次資料結構上機

實驗題目 編寫乙個程式exp3 6.cpp,求解皇后問題 在n n的方格棋盤上,放置n個皇后,要求每個皇后不同行 不同列 不同左右對角線。要求 1 皇后的個數n由使用者輸入,其值不能超過20,輸出所有的解。2 採用類似於棧求解迷宮問題的方法。實驗步驟 包括基本設計思路 演算法設計 函式相關說明 輸入...

C 第三次上機

題目一 假設有乙個字串strfilename d c 程式設計 實驗3 myfile.txt 使用字串方法,取出路徑中的檔名 myfile.txt 要求至少想出三種方法實現 1 using system using system.collections.generic using system.li...

PTA第三次上機

include include include using namespace std class polygon int perimeter 計算多邊形邊長 void display 輸出多邊形邊數和周長 int reachsidelen int polygon perimeter return ...