1. 程式人生 > >BZOJ4755 JSOI2016扭動的回文串(二分答案+哈希)

BZOJ4755 JSOI2016扭動的回文串(二分答案+哈希)

char 分隔符 read lld -o 中間 void return spa

  顯然答案應該是由單串以某位置為中心的極長回文串繼續在另一個串裏拓展得到的。枚舉中間位置二分答案,哈希判斷即可。註意考慮清楚怎麽處理偶回文,比如像manacher一樣加分隔符。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
#define ul unsigned long long
char
getc(){char c=getchar();while ((c<A||c>Z)&&(c<a||c>z)&&(c<0||c>9)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();} while
(c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,ans; ul ha[N],rha[N],hb[N],rhb[N],p[N]; char a[N],b[N],s1[N],s2[N]; ul hash(ul *a,int l,int r,int op) { return a[r]-a[l-op]*p[abs(r-l)+1]; } void solve(ul *a,ul *ra,ul *b,ul *rb,int op,int n) {
for (int i=1;i<=n;i++) { int l=0,r=min(n-i,i-1),len=0; while (l<=r) { int mid=l+r>>1; if (hash(a,i-mid,i,1)==hash(ra,i+mid,i,-1)) len=mid,l=mid+1; else r=mid-1; } ans=max(ans,len); l=1,r=min(i-len+1,n-i-len); while (l<=r) { int mid=l+r>>1; if (op?hash(b,i-len-mid+1,i-len,1)==hash(ra,i+len+mid,i+len+1,-1):hash(a,i-len-mid,i-len-1,1)==hash(rb,i+len+mid-1,i+len,-1)) ans=max(ans,len+mid),l=mid+1; else r=mid-1; } } } void work(int n) { n=n*2+2; for (int i=1;i<=n;i++) ha[i]=ha[i-1]*509+a[i]; for (int i=n;i>=1;i--) rha[i]=rha[i+1]*509+a[i]; for (int i=1;i<=n;i++) hb[i]=hb[i-1]*509+b[i]; for (int i=n;i>=1;i--) rhb[i]=rhb[i+1]*509+b[i]; p[0]=1;for (int i=1;i<=n;i++) p[i]=p[i-1]*509; solve(ha,rha,hb,rhb,0,n),solve(hb,rhb,ha,rha,1,n); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4755.in","r",stdin); freopen("bzoj4755.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); scanf("%s",s1+1),scanf("%s",s2+1); for (int i=n;i>=1;i--) a[i*2+2]=$,a[i*2+1]=s1[i];a[2]=$;a[1]=#; for (int i=n;i>=1;i--) b[i*2+1]=$,b[i*2]=s2[i];b[1]=$;b[n*2+2]=@; work(n); for (int i=n;i>=1;i--) a[i*2+1]=$,a[i*2]=s1[i];a[1]=$;a[n*2+2]=@; for (int i=n;i>=1;i--) b[i*2+2]=$,b[i*2+1]=s2[i];b[2]=$;b[1]=#; work(n); cout<<ans; return 0; }

BZOJ4755 JSOI2016扭動的回文串(二分答案+哈希)