hiho 第一周 最長回文子串

2021-06-28 12:50:18 字數 4612 閱讀 5887

如題:

時間限制:

1000ms

單點時限:

1000ms

記憶體限制:

64mb

小hi和小ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。

這一天,他們遇到了一連串的字串,於是小hi

就向小ho

提出了那個經典的問題:「小ho

,你能不能分別在這些字串中找到它們每乙個的最長回文子串呢?」

小ho奇怪的問道:「什麼叫做最長回文子串呢?」

小hi回答道:「乙個字串中連續的一段就是這個字串的子串,而回文串指的是12421這種從前往後讀和從後往前讀一模一樣的字串,所以最長回文子串的意思就是這個字串中最長的身為回文串的子串啦~」

小ho道:「原來如此!那麼我該怎麼得到這些字串呢?我又應該怎麼告訴你我所計算出的最長回文子串呢?

小hi笑著說道:「這個很容易啦,你只需要寫乙個程式,先從標準輸入讀取乙個整數n(n<=30),代表我給你的字串的個數,然後接下來的就是我要給你的那n個字串(字串長度<=10^6)啦。而你要告訴我你的答案的話,只要將你計算出的最長回文子串的長度按照我給你的順序依次輸出到標準輸出就可以了!你看這就是乙個例子。」

提示一提示二

提示三提示四

×close

提示一良久,小ho仍然沒有頭緒,於是只能向小hi求助。

小hi清了清嗓子,緩緩說道:「讓我從簡單的說起吧,我給你乙個字串,你能不能告訴我它是不是乙個回文串呢?

小ho回答道:「這個我當然可以啦!只要將這個字串反過來,然後比較和原來的字串是不是一樣的不就行了?」

小hi追問道:「也就是說你想要新建乙個字串咯?」

小ho道:「那是當然,不然怎麼比較呢?」

小hi笑道:「但是你有沒有注意到你在比較原來的字串a和新字串b的時候,a的第乙個字元就是b的最後乙個字元,而a的最後乙個字元就是b的第乙個字元,那麼這樣就比較了兩次是不是浪費了效率呢?」

小ho恍然道:「似乎是這樣的!我知道了,我也不需要新建乙個字串了,我只需要比較a的第乙個字元和最後乙個字元是否相同,第二個字元和倒數第二個字元是否相同,以此類推,這樣就只要比較字串長度的一半次數就行了是不是?」

小hi回答道:「沒錯!那你對於乙個字串,一一枚舉它的子串,然後判斷這個子串是不是回文子串,如果是的話就更新當前儲存的最長的那乙個,是不是就可以了?

小ho開心道:「是的!這個問題是不是就這麼解決了?」

小hi嘆息道:「nonono!你這最多也就拿個60分吧。」

小ho遺憾的說道:「才及格啊,那我要怎麼多拿點分呢?」

close

×close

提示二小hi道:「不急不急,待我慢慢道來,你有沒有想過之前的解法有沒有什麼問題?」

小ho問道:「有什麼問題?」

小hi道:「你想想,如果乙個字串的[3, 7]這一段已經不是回文子串了,[2, 8]這一段還有可能是回文子串麼?

小ho驚道:「好像不可能,那我之前不是有很多的計算都白費了,有沒有什麼辦法來解決這個問題呢?我得好好想想!」言罷,小ho沉思了起來。

良久,代表著成功的微笑出現來的小ho的嘴邊:「我知道了!我在列舉子串的時候換一種方式來進行列舉,不是列舉它的起止位置而是嘗試列舉子串的中心位置,然後再從小到大依次列舉這個子串的長度,一旦發現已經不是乙個回文串了就繼續嘗試下乙個中心位置,這樣,似乎就能夠避免掉很多問題呢!」

小hi讚許的點了點頭,說道:「沒錯,這樣的確會在一些情況下降低用於計算的時間呢,但是乙個全是a的字串,你這樣的列舉方法似乎也沒有多大用處呢?不過這樣你也能拿個80分了哦!」

小ho點了點頭,說道:「沒錯,在最壞情況下,這種方法並沒有比之前的方法好到**去,但是我的直覺告訴我肯定有更加高效的方法來進行計算呢,讓我再好好想想吧!。」

close

×close

提示三小ho這一想就是三天,小hi也是看不下去了,決定來開導開導小ho:「小ho,你有沒有想過,在之前的計算中,計算出以每乙個位置為中心的最長回文子串的長度有沒有什麼用呢?」

小ho答道:「我想想,如果以第5個字元為中心的最長回文子串的長度是5的話,這就告訴了我[3, 7]這一段是乙個回文子串,所以呢?」

小hi繼續提示道:「假設這時候你想要計算以第6個字元為中心的最長回文子串的長度,你有沒有什麼已知的資訊了?」

小ho邊想邊說道:「唔,首先第6個字元和第4個字元是一樣的,第7個字元和第3個字元是一樣的,而第5個字元本身就肯定和第5個字元一樣,那麼如果[3, 5]這一段是回文子串的話,那麼[5, 7]這一段肯定也是回文子串。也就是說,如果令f[i] 表示以第i個字元為中心的最長回文子串的長度,我們就會有f[i] >= f[i–2]?」

「不對,還要考慮到f[i – 1]的值,如果f[i – 1]太小就沒有意義了,應該是f(i)≥min⁡。」小ho接著補充道。

「沒錯,但是還有乙個問題,如果此時我告訴你f(5) = 1,但是f(4) = 7, f(2) = 3呢?」小hi追問道。

小ho想了想,回答道:「理論上來說,我可以通過這些資訊知道f(6)>=3,但是由於f(5)=1所以我只能計算出來f(6)>=-1我知道了,我不應該是通過f(i – 1)來輔助計算,而是通過使得右邊界(j + f(j) / 2)最大的那個j來輔助計算才是,所以公式將變成f(i) ≥ min這種形式了!」

小hi繼續問道:「那知道了這個公式之後,你打算怎麼做呢?」

小ho想也沒想便道:「這簡單,我只要在之前列舉中心位置那種方法的基礎上,統計使得回文串右邊界(j + f(j) / 2)最大的那個j,然後再計算每乙個i的時候,都可以通過f(i)≥min⁡這個公式來知道f(i)的乙個最小值,這樣即使是在我們所提到的那種最壞情況下,也可以節省掉很多不必要的計算呢~

close

×close

提示四一晃就是一周過去了,小hi還是沒有看到小ho寫的程式,於是決定上門去問問。到了小ho家,小hi驚訝的發現小ho對著電腦螢幕,一臉鬱悶的樣子,於是他走上前問道:「小ho小ho,你怎麼了啊?」

小ho一點精神也沒有的回答道:「就是上週的那個回文子串的程式啊,我寫的時候發現我們當時考慮的解決方法只能處理長度為奇數的回文子串,長度為偶數的回文子串似乎要進行一點點細微的修改,但是這樣修改過後就不能用我們最後寫出的那個公式來互相幫助進行運算了,要進行很複雜的討論,我就是一直在想有沒有很優美的方法能來解決這個問題。」

小hi驚訝道:「你就想這個想了一周麼?我猜你一定是繞進了分類討論的這個胡同裡走不出來了,為什麼不想想有沒有別的解決方法呢?」

小ho問道:「還有什麼解決方法呀?」

小hi答道:「既然長度為偶數的回文子串不好處理,我們為什麼不去掉這些回文子串,只處理長度為奇數的回文子串呢?」

小ho嘆息道:「但是長度為偶數的回文子串也可以是答案啊!」

「除非……」小hi插嘴道。

「除非什麼?」小h問道。

「你將所有的長度為偶數的回文子串都變成長度為奇數的回文子串啊,你想想之所以是為偶數,那是因為沒有乙個中心字元,但是如果我們在原來字串的基礎上,在任意兩個相鄰的字元間都插入乙個特殊字元,是不是無論是原來字串中長度為奇數的回文子串還是長度為偶數的回文子串,在新的字串中都有乙個長度為奇數的回文子串與之進行對應呢?」

「哦!我了解了,這樣我只需要對新的字串按照我們之前的演算法進行計算,統計出的最長回文子串將那些特殊字元去掉之後,就是原來字串裡的最長回文子串了。」小ho開心的笑道,一連幾天的鬱悶也是一掃而空。

「但是要注意哦,我們希望得到的最長是原來字串裡的最長,而不是新字串裡的最長,畢竟特殊字元的個數會因為中心字元是不是特殊字元而有差別的哦。」小hi提醒道。

「恩恩,這樣我總能拿到滿分了吧?」

「沒錯呢!」

close

樣例輸入

3

abababa

aaaabaa

acacdas

樣例輸出

7

53

官方精簡的可怕的**:

自己寫的真是又臭又長! 根本不好意思貼

#include

#include

#include

char str[1000002 + 1200];

int fast(char *p)

return ans;

}int main()

return 0;

}

hiho一下第一周 最長回文子串

類似於kmp的思想,利用已經匹配的資訊計算未匹配的資訊。基本原理就是 我們將f i 定義為以i為中心的最長回文串長度。那麼如果有f 5 7,f 4 3,那麼我們可以得到f 6 3.以此來減少比較次數。當然還有一些細節要處理。比如回文串長度的奇偶性。這個是我自己寫的版本,不是很精簡。include i...

hiho一下第一周 最長回文子串

時間限制 1000ms 單點時限 1000ms 記憶體限制 256mb 小hi和小ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。這一天,他們遇到了一連串的字串,於是小hi 就向小ho 提出了那個經典的問題 小ho 你能不能分別...

hiho一下 第一周(最長回文子串)

時間限制 1000ms 單點時限 1000ms 記憶體限制 64mb 小hi和小ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。這一天,他們遇到了一連串的字串,於是小hi就向小ho提出了那個經典的問題 小ho,你能不能分別在這些...