資料結構與演算法 字串

2021-07-06 02:15:29 字數 2703 閱讀 8938

判斷乙個串是不是回文串,往往要分開編寫,造成**的拖沓

int longestpalindrome(const char * s, int n)

return

max;

}void longestpalindrome_test()

上面的迴圈中,對於回文長度本身的奇偶性,我們進行區別處理。這樣有點拖沓。我們根據乙個簡單的事實:長度為n的字串,共有n-1個「鄰接」,加上首字元的前面後某字元的後面,共有n+1的「空(gap)」。因此,字串本身和gap一起,共有2n+1個,必定是奇數。

* abba –> #a#b#b#a# 此回文這樣處理後長度4–>9

* aba –> #a#b#c# 此回文這樣處理後長度3–>7

因此,將待計算母串擴充套件成gap串,則裡面的回文字串的長度都變成了奇數,我們計算的時候只用考慮奇數匹配即可。

字串12212321–> s = 「$#1#2#2#1#2#3#2#1#」;( 為了統一處理,最前面加乙個特殊字元。則下標從1開始)

用乙個陣列p[i]來記錄以字元s[i] 為中心的最長回文字串向左/向右擴張的長度(包括s[i]),比如s和p的對應關係:

s: "#    1    #    2    #    2    #    1    #    2    #    3    #    2    #    1    #";

p:

p[i]-1正好是原字串中回文串的總長度。

「# 1 # 2 # 2 # 1 #」

「———1 2 3 4 5」

p[i] = 5

原始回文字串長度是偶數的情況,則在gap串中p[i]的值多了中間的乙個#。p[i]-1 == length

「# 1 # 2 # 3 # 2 # 1 # 」

「———————1 2 3 4 5 6 」

p[i] = 6

原始回文字串長度是奇數的情況,則在gap串種p[i]的值多了最後的#號。p[i]-1 == length

目前,只要知道了陣列p的值,就能求得最多長回文的大小了。但是,怎麼求呢p呢?請看下文。

s: "#    1    #    2    #    2    #    1    #    2    #    3    #    2    #    1    #";

p:

我們的任務,假定已經得到了前i個值,考察i+1如何計算。即:在p[0…i-1]已知的情況下,利用其中資訊,計算p[i]的值。

1. 通過簡單遍歷,找到i個三元組,0<=k<=i-1。(以k為中心的字元形成的最大回文子串的最右位置是k+p[k]-1)

2. 以k+p[k]為關鍵字,挑選出這i個三元組中,k+p[k]最大的那個三元組,不妨記作(id,p[id],id+p[id])。進一步,為了簡化,記mx=p[id]+id,因此,得到三元組為(id,p[id],mx),這個三元組的含義非常明顯:所有i個三組中,向右達到最遠的位置,就是mx。

3. 在計算p[i]的時候,考察i是否落在了區間[0,mx)中;

-1. 若i在mx的右側,說明[0,mx)沒有能夠控制住i,p[0..i-1]都已知,無法給p[i]的計算帶來有價值的資訊。

-2. 若i在mx的左側,說明[0,mx)控制(也有可能部分控制)了i,現在以圖示來詳細考察這種情況。這就是manacher遞推關係。

記i關於id的對稱點位j(=2*id - i),若此時滿足條件mx-i

>

p[j].

記my為mx關於id的對稱點(my

=2∗i

d−mx

); 由於以s[id]為中心的最大回文字串為s[my+1…id…mx-1],

即:s[my+1….,id]與s[id,…,mx-1]對稱,而i和j關於id對稱,因此p[i]=pj。

記i關於id的對稱點位j(=2

∗id−

i ),若此時滿足條件mx-i

<

p[j]:

記my為mx關於id的對稱點(my

=2∗i

d−mx

); 由於以s[id]為中心得最大回文字串為s[my+1,…id…mx-1],即s[my+1,…,id]與s[id,…,mx-1]對稱,而i和j關於id對稱,因此p[i]至少等於mx-i(途中綠框部分)

manacher**

void manacher(char * s, int *p)

}}void manacher_test()

snew[sizenew] = '\0';

cout

<< snew << endl;

int * p = new

int[sizenew];

manacher(snew,p);

print(p,sizenew);

}

p[j] > mx - i: p[i] = mx - i

p[j] < mx - i: p[i] = p[j]

p[j] = mx - i: p[i] >= p[j]

根據上面的原始碼,原始manacher演算法,前兩個等號都是大於等於。

下面是改進的manacher演算法:

void manacher2(char * s, int * p)

else}}

else

if (mx < i + p[i])

}}

資料結構與演算法 字串

生成n對括號的所有合法排列 描述 給定乙個非負整數n,生成n對括號的所有合法排列。解答 該問題解的個數就是卡特蘭數,但是現在不是求個數,而是要將所有合法的括號排列列印出來。該問題和 程式設計之美 的買票找零問題一樣,通過買票找零問題我們可以知道,針對乙個長度為2n的合法排列,第1到2n個位置都滿足如...

資料結構與演算法 字串

題型1 如何統計字元中有多少個單詞?方法1 使用空格作為分隔。如果測出某乙個字元為非空格,而它前面的單詞是空格,則表示 新的單詞開始了 此時單詞數count累加1.如果當前字元為非空格而其前面的字元也是非空格,則意味著仍然是原來那個單詞的繼續,count不應再累加1.方法2 使用sstream中的i...

C C 資料結構與演算法 字串)

串 string 是有零個或多個字元組成的有限序列,有名叫字串。空格串和空串不一樣,空格串是有內容有長度的,而且可以不止乙個空格。線性表更關注的是單個元素的操作,比如查詢乙個元素,插入或刪除乙個元素,但串中更多的是查詢子串位置 得到指定位置子串 替換子串等操作。adt 串 string data 串...