BZOJ2794: [Poi2012]Cloakroom 离线+背包
BZOJ1129: [POI2008]Per 数学+树状数组

BZOJ1524: [POI2006]Pal hash+恶心题

shinbokuow posted @ Sep 15, 2015 07:41:15 PM in BZOJ with tags hash 恶心题 , 1510 阅读

 

题解:

玛德现在我做什么题感觉什么题恶心。。

一定是我心态不对。

这题就随便分类讨论一下就行了。

假设$x+y$是一个回文串。

若$len_x=len_y$,必定有$x=y$。

若$len_x>len_y$,$y$必定是$x$的前缀,且剩下的部分是回文串。

若$len_x<len_y$,$x$必定是$y$的后缀,且剩下的部分是回文串。

我们只需要枚举比较长的串,然后利用hash随便判判就行了。

然而hash各种卡,又WA又T一时爽。。。

为了保证正确性写的双hash,现在依然在T中QoQ。

代码:

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

typedef long long ll;
#define N 2000010
int id,be[N],en[N],tot;
char s[N],rs[N],tmp[N];
int f1[N],rf1[N],pow1[N];
int f2[N],rf2[N],pow2[N];

static const int seed1=233;
static const int mod1=1000000007;
static const int seed2=2333;
static const int mod2=1000000009;
//static const int seed3=131;
//static const int mod3=998244353;

typedef pair<int,int> pii;
#define mp make_pair

pii get(int l,int r){
	int hash1=(f1[l]-(ll)f1[r+1]*pow1[r-l+1]%mod1+mod1)%mod1;
	int hash2=(f2[l]-(ll)f2[r+1]*pow2[r-l+1]%mod2+mod2)%mod2;
	//printf("%d %d\n",hash1,hash2);
	return mp(hash1,hash2);
}

pii getr(int l,int r){
	int hash1=(rf1[l]-(ll)rf1[r+1]*pow1[r-l+1]%mod1+mod1)%mod1;
	int hash2=(rf2[l]-(ll)rf2[r+1]*pow2[r-l+1]%mod2+mod2)%mod2;
	return mp(hash1,hash2);
}

//map<pii,int>M;
struct Hashset{
	static const int Mod=131313;
	int head[Mod],next[N],v[N],ind;
	pii f[N];
	void reset(){
		ind=0;
		memset(head,-1,sizeof head);
	}
	void insert(pii x){
		int ins=(x.first+x.second)%Mod;
		for(int j=head[ins];j!=-1;j=next[j])
			if(f[j]==x){
				++v[j];
				return;
			}
		f[ind]=x;
		v[ind]=1;
		next[ind]=head[ins];
		head[ins]=ind++;
	}
	int operator[](pii x){
		int ins=(x.first+x.second)%Mod;
		for(int j=head[ins];j!=-1;j=next[j])
			if(f[j]==x)
				return v[j];
		return 0;
	}
}M;

bool check(int l,int r){
	if(l==r)
		return 1;
	int hl=(r-l+1)>>1;
	return get(l,l+hl-1)==getr(tot-r+1,tot-r+hl);
}

int main(){
	//clock_t beg=clock();
#ifndef ONLINE_JUDGE
	//freopen("tt.in","r",stdin);
#endif
	int n,i,j,len;
	scanf("%d",&n);
	for(i=1;i<=n;++i){
		scanf("%d%s",&len,tmp+1);
		++id;
		be[id]=en[id-1]+1;
		en[id]=en[id-1]+len;
		for(j=1;j<=len;++j)
			s[++tot]=tmp[j];
	}
	memcpy(rs,s,sizeof s);
	for(i=1;i<=(tot>>1);++i)
		swap(rs[i],rs[tot-i+1]);
	
	for(pow1[0]=pow2[0]=1,i=1;i<=tot;++i){
		pow1[i]=(ll)pow1[i-1]*seed1%mod1;
		pow2[i]=(ll)pow2[i-1]*seed2%mod2;
	}
	
	for(i=tot;i>=1;--i){
		f1[i]=((ll)f1[i+1]*seed1+(s[i]-'a'+1))%mod1;
		rf1[i]=((ll)rf1[i+1]*seed1+(rs[i]-'a'+1))%mod1;
		f2[i]=((ll)f2[i+1]*seed2+(s[i]-'a'+1))%mod2;
		rf2[i]=((ll)rf2[i+1]*seed2+(rs[i]-'a'+1))%mod2;
	}
	
	M.reset();
	for(i=1;i<=n;++i)
		M.insert(get(be[i],en[i]));
		//M[get(be[i],en[i])]++;
	
	long long ans=0;
	for(i=1;i<=n;++i){
		ans+=M[get(be[i],en[i])];
		for(j=be[i];j<en[i];++j)
			if(check(j+1,en[i]))
				ans+=M[get(be[i],j)];
		for(j=tot-en[i]+1;j<tot-be[i]+1;++j)
			if(check(be[i],tot-j))
				ans+=M[getr(tot-en[i]+1,j)];
	}
	
	cout<<ans<<endl;
	//printf("%ldms\n",clock()-beg);
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter