日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Manacher 算法模板

發布時間:2025/3/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Manacher 算法模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

  • 在字符串的題目中,有時會遇上 回文串 這樣一個名詞

  • 顧名思義,回文串 就是 正讀和反讀都一樣的字符串

  • 最長回文子串 ,就是在一個字符串的所有子串中,是回文串且長度最長的那個

  • 求最長回文子串最普通的方法是 O(N2) ,即枚舉一個點往兩邊擴展

  • 但是在有些題目中,N 卻十分的大

  • 那么我們就要用到 時間空間復雜度都是 O(N)Manacher 算法

用法

  • 在處理回文串時,我們常常會被 中間字符是一個還是兩個 這樣的問題困擾

  • 但是在機智的 Manacher 算法 中,這個問題得到了完美的解決

  • 在每兩個字符中間插入一個不會出現的分隔符(如:#)

  • 之后在頭尾插入一個還是沒有出現的分隔符(如:*)來防止 While 出界

  • 這樣處理起來就方便很多了!

  • 設讀入的字符串為 s[i]

  • 記錄 p[i] 表示 以 s[i] 為中心往兩邊擴展的最大長度

  • 觀察可知,實際的回文串長度即為當前的 p[i]?1

  • 再記錄一個數 idp[id]+id表示在 i 位置前所有回文串中能延伸到的最右端的位置

  • 如下圖:

  • 算法核心就是:

  • if(p[id]+id>i) p[i]=min(p[id?2?i],p[id]+id?i); else p[i]=1;

  • 當之前所有回文串中能延伸到的最右端覆蓋過 i 時,則取最小值,否則 p[i]=1 ,及自己本身

  • 這樣不斷維護 p[i]id ,就能在 O(N) 內求出 最長回文子串 了!

  • 至于為什么時間是線性的,由于最有端 p[id]+id 最多只能移動 N 次,

  • 有效移動的操作就嚴格線性啦!!

  • 下面附上模板:

void Manacher() {scanf("%s",s);int len=strlen(s);for(int i=len;i>=0;i--){int k=i*2+1;s[k+1]=s[i],s[k]='#';}//插入分隔符len*=2;s[ans=id=0]='*';for(int i=2;i<=len;i++){if(p[id]+id>i) p[i]=min(p[id*2-i],p[id]+id-i); else p[i]=1;while(s[i-p[i]]==s[i+p[i]]) p[i]++;if(p[i]+i>p[id]+id) id=i;if(p[i]>ans) ans=p[i];}//處理、計算 }
  • 注釋:s[i]p[i]id 如題意義,ans 表示 最長回文子串 的長度,而 len 是原串長度

總結

  • 這個 Manacher 算法效率極高,時間空間都是 O(N) 線性的

  • 再者代碼極短,所以使用起來十分方便,應多多使用!!!

總結

以上是生活随笔為你收集整理的Manacher 算法模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。