判斷乙個串是不是回文串,往往要分開編寫,造成**的拖沓
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 串...