蓝书(算法竞赛进阶指南)刷题记录——POJ3974 Palindrome(二分+Hash / manacher)

版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/86410026

题目:POJ3974.
题目大意:给定一个字符串,求它的最长回文子串.

一看是道manacher的裸题,于是可以拿来manacher练手.

但是既然在蓝书上说可以用hash解决,那就当get一个新技能写个hash吧(虽然在考场上时间不够了manacher也比二分+hash好写…).

大概就是说我们枚举对称中心,然后二分一下最长可以向两边拓展的长度,然后暴力判定两边是否相等.这就可以想到正着预处理一遍hash值,反着预处理一遍hash值来做到 O ( 1 ) O(1) 判定.

二分+hash代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> 
  using namespace std;

#define Abigail inline void
typedef long long LL;
typedef unsigned long long ULL;

const int N=2000000;
const ULL P=131;

char c[N+9];
int n,cas,ans;
ULL s1[N+9],s2[N+9],Pow[N+9];

ULL Hash(ULL *s,int l,int r){return s[r]-s[l-1]*Pow[r-l+1];}
ULL reHash(ULL *s,int l,int r){return s[l]-s[r+1]*Pow[r-l+1];}

bool check(int mid,int len){
  if (mid-len<0||mid+len-1>n) return false;
  return Hash(s1,mid-len+1,mid)==reHash(s2,mid,mid+len-1);
}

int solve(int mid){
  int len=0;
  for (int i=19;i>=0;--i)
    if (check(mid,len+(1<<i))) len+=1<<i;
  return len;
}

Abigail start(){
  ans=0;
  n=strlen(c+1);
  c[0]='^';
  for (int i=n;i>=1;--i)
    c[i<<1|1]='#',c[i<<1]=c[i];
  c[1]='#';
  n=n<<1|1;
  Pow[0]=1;
  for (int i=1;i<=n;++i)
    Pow[i]=Pow[i-1]*P;
  for (int i=1;i<=n;++i)
    s1[i]=s1[i-1]*P+c[i];
  for (int i=n;i>=1;--i)
    s2[i]=s2[i+1]*P+c[i];
}

Abigail work(){
  for (int i=1;i<=n;++i)
    ans=max(ans,solve(i)-1);
}

Abigail outo(){
  printf("Case %d: %d\n",cas,ans); 
}

int main(){
  while (~scanf("%s",c+1)&&c[1]^'E'){
  	++cas;
  	start();
    work();
    outo();
  }
  return 0; 
}

manacher代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> 
  using namespace std;

#define Abigail inline void
typedef long long LL;
typedef unsigned long long ULL;

const int N=2000000;

char tmp[N+9];
int pal[N+9];

int manacher(char *c,int n){
  for (int i=1;i<=n;++i)
    tmp[i<<1]=c[i],tmp[i<<1|1]='#';
  tmp[0]='^';tmp[1]='#';
  n=n<<1|1;
  int p=0,r=0,ans=0;
  for (int i=1;i<=n;++i){
  	pal[i]=r>i?min(pal[2*p-i],r-i):1;
  	while (tmp[i+pal[i]]==tmp[i-pal[i]]) ++pal[i];
  	if (i+pal[i]>r) r=i+pal[i],p=i;
  	ans=max(ans,pal[i]);
  }
  return ans-1;
}

char c[N+9];
int n,ans,cas;

Abigail work(){
  n=strlen(c+1);
  ans=manacher(c,n);
}

Abigail outo(){
  printf("Case %d: %d\n",cas,ans); 
}

int main(){
  while (~scanf("%s",c+1)&&c[1]^'E'){
  	++cas;
    work();
    outo();
  }
  return 0; 
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/86410026
今日推荐