bzoj 3555: [Ctsc2014]企鹅QQ hash

       哈哈20s卡过~\(≧▽≦)/~

       不过用的是双hash。。。跑得慢也正常。。

       sb题。直接枚举不同的哪一位其余的hash判断是否相同即可。具体可以快排或者用哈希表来统计答案。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define mod1 1000000009
#define mod2 900000083
#define ll long long
#define N 30005
#define M 205
using namespace std;

int n,m,ans,pw1[M],pw2[M],sv1[N][M],sv2[N][M]; char ch[M];
struct hsh_node{
	int cnt,tot,h[N],fst[2010527],px[N],py[N],pu[N],pv[N],len[N],nxt[N];
	void clr(){
		while (cnt) fst[h[cnt--]]=0; tot=0;
	}
	void ins(int x,int y,int u,int v){
		int z=((ll)x*1000003+y)%2010527,w=((ll)u*2000003+v)%2010527,p;
		z=(z*103+w)%2010527;
		for (p=fst[z]; p; p=nxt[p])
			if (px[p]==x && py[p]==y && pu[p]==u && pv[p]==v){
				ans+=len[p]; len[p]++;
				return;
			}
		if (!fst[z]) h[++cnt]=z;
		px[++tot]=x; py[tot]=y; pu[tot]=u; pv[tot]=v;
		len[tot]=1; nxt[tot]=fst[z]; fst[z]=tot;
	}
}hsh;
int get1(int x,int y,int z){ return (sv1[x][y]-(ll)sv1[x][y+z]*pw1[z]%mod1+mod1)%mod1; }
int get2(int x,int y,int z){ return (sv2[x][y]-(ll)sv2[x][y+z]*pw2[z]%mod2+mod2)%mod2; }
int main(){
	scanf("%d%d",&n,&m); int i,j; scanf("%d",&i);
	pw1[0]=pw2[0]=1;
	for (i=1; i<=m; i++){
		pw1[i]=(ll)pw1[i-1]*223%mod1; pw2[i]=(ll)pw2[i-1]*233%mod2;
	}
	for (i=1; i<=n; i++){
		scanf("%s",ch+1);
		for (j=m; j; j--){
			sv1[i][j]=((ll)sv1[i][j+1]*223+ch[j])%mod1;
			sv2[i][j]=((ll)sv2[i][j+1]*233+ch[j])%mod2;
		}
	}
	for (i=1; i<=m; i++){
		hsh.clr();
		for (j=1; j<=n; j++)
			hsh.ins(get1(j,1,i-1),get2(j,1,i-1),get1(j,i+1,m-i),get2(j,i+1,m-i));
	}
	printf("%d\n",ans);
	return 0;
}

by lych

2016.5.26

你可能感兴趣的:(字符串,hash)