解題筆記(14) 幾個字串的問題

2021-05-26 18:56:29 字數 3795 閱讀 1984

字串問題是面試中經常出現的問題,這類問題有很多,難以不一。下面是幾道字串的題目,網上都能找到解答,自己實現了一下,供網友參考。感覺演算法重要的是要有正確的思路,實現起來不是問題。自己一定要多思考,這樣收穫可能會更多一點。

問題1:找兩個字串的最長公共子串。

具體描述,

如果字串一的所有字元按其在字串中的順序出現在另外乙個字串二中,則字串一稱之為字串二的子串。注意,並不要求子串(字串一)的字元必須連續出現在字串二中。請編寫乙個函式,輸入兩個字串,求它們的最長公共子串,並列印出最長公共子串。

思路:演算法書上一般都有介紹,就是用動態規劃的思想。關鍵是要找到最優子結構性質,這一點比較難。另外乙個經常問到的問題「求子陣列的最大和」,用的也是動態規劃的思想。找兩個字串最長公共子串的核心就是找最優子結構。

設序列x = 和y = 的最長公共子串為z = ,則

1 若xm= yn且zk=xm=yn, 則zk-1是xm-1和yn-1的最長公共子串

2 若xm!=yn且zk!=xm,則z是xm-1和y的最長公共子串

3 若xm!=yn且zk!=yn,則z是x和yn-1的最長公共子串

其中xm-1= ,yn-1 = zk-1 =

有了上述關係,則很容易得到遞推的式子。用乙個二維陣列 r 記錄結果,其中z[i][j]表示xi和yj的最長公共子串長度。

(1)如果i = 0或j = 0,z[i][j] = 0

(2)如果xi和yj相等,z[i][j] = z[i-1][j-1] + 1

(3) 如果xi和yj不相等,z[i][j] = max

基本上差不多了,但是題目要求列印最長公共子串,只要用乙個陣列r記錄得到最長公共子串的過程,其中r[i][j]表示z[i][j]的值是由哪個子問題的解得到的。

//函式功能 : 列印最長公共子串

//函式引數 : x為源字串1,y為源字串2,r為記錄的過程,row為r的行座標,col為r的列座標

//返回值 : 空

void lcs_print(const char *x, const char *y, int **r, int row, int col)

else

}} }

//列印最長公共子串

lcs_print(x, y, r, lenx, leny);

//記錄最大長度

int lcs = c[lenx][leny];

//釋放空間

for(i = 0; i <= lenx; i++)

delete c;

delete r;

r = c = null;

return lcs;

}

問題2:在字串中刪除特定元素

具體描述,輸入兩個字串,從第一字串中刪除第二個字串中所有的字元。例如,輸入

」they are students.」

和」aeiou」

,則刪除之後的第乙個字串變成

」thy r stdnts.」。

思路:這是字元查詢的乙個問題,最簡單的就是考察第二個字串的每個字元,然後檢查第乙個字串中有沒有這個字元,有的話刪除。這樣的時間複雜度是o(mn)。對於查詢,我們容易想到二分查詢、雜湊這些概念。雜湊的查詢是非常快,時間複雜度為o(1)。如果能聯想到雜湊,那麼很容易就能給出下面的解法,相信很多人都能想到。需要乙個256位元組的陣列,記錄第二個字串中每個字元的出現情況,0表示未出現,1表示出現。然後遍歷第乙個字串,針對每個字元,去查詢記錄陣列,以決定刪除與否。

參考**:

//函式功能 : 在字串中刪除特定字元

//函式引數 : psrc為源字串,pdel為特定字符集

//返回值 : 空

void deletespecialchars(char *psrc, char *pdel)

; for(int i = 0; i < lendel; i++) //建立刪除字元的索引

hash[pdel[i]] = true;

//開始刪除

char *pcur = psrc;

while(*psrc != '\0')

*pcur = '\0';

}

問題3:左旋轉字串,其實也可以左旋陣列

具體描述,定義字串的左旋轉操作:把字串前面的若干個字元移動到字串的尾部。如把字串abcdef左旋轉2位得到字串cdefab。請實現字串左旋轉的函式。要求時間對長度為n的字串操作的複雜度為o(n),輔助記憶體為o(1)。

思路:用了乙個小技巧,如果旋轉的字串為xy,其中y是要旋轉到x前面的。只要分別將子字串 x 和 y 翻轉,然後再將整個字串再做一次翻轉即可。stl的乙個演算法rotate就是用了這個。

參考**:

//函式功能 : 將字串翻轉

//函式引數 : pbegin指向第乙個字元,pend指向最後乙個字元

//返回值 : 空

void reversestring(char *pbegin, char *pend)

}//函式功能 : 將字串左旋 n 位

//函式引數 : psrc為源字串,n為左旋位數

//返回值 : 空

void leftrotatestring(char *psrc, unsigned n)

問題4:在乙個字串中找到第乙個只出現一次的字元。如輸入abaccdeff,則輸出b。 

思路:這一題不難,因為每個字元只有8位,因此可以用計數法。首先統計字串中每個字元的出現次數,然後從頭遍歷字串,對於當前字元,查詢統計表,如果出現的次數為1,則輸出該字元即可。

參考**:

//函式功能 : 在乙個字串中找到第乙個只出現一次的字元

//函式引數 : pstr為源字串

//返回值 : 目標字元

; char *ptmp = pstr;

while(*ptmp != '\0') //統計字串中每個字元出現的次數

while(*pstr != '\0') //遍歷字串,找到第乙個只出現一次的字元

return *pstr; //找到的字元

}

問題5:寫乙個函式,它的原形是int continumax(char *outputstr,char *intputstr)。功能:在字串中找出連續最長的數字串,並把這個串的長度返回,並把這個最長數字串付給其中乙個函式引數outputstr所指記憶體。

例如:"abcd12345ed125ss123456789"的首位址傳給intputstr後,函式將返回9,outputstr所指的值為123456789

思路:這一題比較簡單,掃瞄一遍字串即可,遇到數字時將數字個數加1,然後與最長串比較,如果長度大於最長串,更新最長串;遇到非數字時,將數字計數器清零。

參考**:函式名和形參名修改了一下,個人習慣。

//函式功能 : 在字串中找出連續最長的數字串

//函式引數 : psrc表示源串,pdest記錄最長數字串的起始位置

//返回值 : 最長數字串的長度

int continuemax(char *psrc,char * &pdest)

} else

cnt = 0;

psrc++;

} if(cnt > max)

return max;

}

寫幾個字串演算法

1 實現strstr函式 函式原型是char strstr char str1,char str2 作用是找出str2字串在str1字串中第一次出現的位置 不包括str2的串結束符 如果找到返回該位置的指標。若找不到,返回null指標。2 實現strcpy函式 char strcpy char de...

Oracle幾個字串函式

平常我們用oracle主要有兩種字串型別 1 char始終為固定的長度,如果設定了長度小於char列的值,則oracle會自動用空格填充的。當比較char時,oracle用空格將其填充為等長,再進行比較 2 varchar2資料型別為可變長度,雖然與varchar資料型別是同義的,但在今後的orac...

幾個字串匹配演算法

下面依次來說說樸素演算法,rabin karp演算法,knuth morris pratt演算法,boyer moore演算法,sunday演算法,以及aho corasick等演算法。樸素演算法是一種非常簡單的演算法,時間複雜度是o nm n為文字串長度,m為模式串長度,下同 不需要預處理。int...