Fami通新一週銷量榜 《馬里奧高爾夫:超級沖沖衝》二連冠
阿新 • • 發佈:2021-07-09
1. manacher 馬拉車
思路
- 迴文串長度有奇有偶,奇迴文串有對稱中心,那偶迴文串呢,所以我們就在每兩個字串之間加一個#,再在整個串前面加一個 % ,這樣奇偶串就可以用按一種方法處理了,比如abcd --> %a#b#c#d#
- 我們可以用O(n) 求出r陣列,r[i]是以i為對稱中心的迴文串半徑(長度包括i),令mx是迴文串覆蓋的最右邊界的右邊一位,p是覆蓋最右邊界的迴文串的對稱中心,這時我們要求r[i],暴力會TLE,當p<mx時,我們考慮r[i]可以從r[2 * p - i] 處已確認對稱的部分轉移過來,r[i]=min (mx-p,r[ 2 * p - i ]),之後繼續嘗試暴力向外拓展,看r[i]是否能增大
code
#include<bits/stdc++.h> #define N 22000010 #define mod 998244353 #define int long long using namespace std; int n,ans; int r[N]; char a[N]; template<class T> inline void read(T &x) { x=0;int g=1;char s=getchar(); for (;s<'0'||s>'9';s=getchar()) if (s=='-') g=-1; for (;s>='0'&&s<='9';s=getchar()) x=(x<<1)+(x<<3)+(s^48); x*=g; } signed main() { int i,j,op,x,y,z; scanf("%s",a+1); n=strlen(a+1); for (i=n;i;i--) a[2*i]=a[i],a[2*i+1]='#';a[1]='#';a[0]='$'; int p=1,mx=1; n=2*n+1; for (i=1;i<=n;i++) { if (mx<=i) r[i]=1; else r[i]=min(mx-i,r[2*p-i]); while(a[i+r[i]]==a[i-r[i]]) r[i]++; if (i+r[i]>mx) { mx=i+r[i];p=i; } ans=max(ans,r[i]); } printf("%lld\n",ans-1); return 0; }