bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

首先,这篇博客,是用来搞笑的。

看了一眼题目,内心:好像是后缀自动机啊,可是不会写sad...看起来大家运行时间不是很长啊暴力吧!然后写了一个又长又慢的弱智暴力,意料之中的TLE了。

要是发现代码的问题,或者有比较好的暴力idea,欢迎交流!

#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<set>
#define N 11000
#define M 100010
#define X 60010
using namespace std;
typedef long long LL;
set<LL>Q1,Q2;
int n,qq,len[N],st[N],mlen,len2[X],num[X],ans[X];
char s[M],c[M];
LL mod[2]={1000000007,1000000009},d[M][2],ci[M][2],bas=127,hah[X][2];
LL hsh(int l,int r,int k,bool x)
{
	LL k1=d[l-1][k];
	if(x)k1=0;
	return (d[r][k]-k1*ci[r-l+1][k]%mod[k]+mod[k])%mod[k];
}
bool cmp(int a,int b)
{
	return len2[a]<len2[b];
}
void hhh(int th,int fr,int to)
{
	if(th>mlen)return ;
	for(int i=1;i<=n;i++)
	if(len[i]>=th)
	{
		Q1.clear(),Q2.clear();
		for(int j=0;j<len[i];j++)
		{
			if(len[i]-j<th)break;
			LL a1=hsh(st[i]+j,st[i]+j+th-1,0,(j==0)),a2=hsh(st[i]+j,st[i]+j+th-1,1,(j==0));
			Q1.insert(a1),Q2.insert(a2);
		}
		for(int k=fr;k<=to;k++)
		{
			int p=num[k];
			if(Q1.count(hah[p][0])&&Q2.count(hah[p][1]))ans[p]++;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&qq);
	st[0]=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",c);
		len[i]=strlen(c);
		if(len[i]>mlen)mlen=len[i];
		st[i]=st[i-1]+len[i-1];
		for(int j=0;j<len[i];j++)s[j+st[i]]=c[j];
	}
	ci[0][0]=ci[0][1]=1;
	for(int i=1;i<=mlen;i++)ci[i][0]=ci[i-1][0]*bas%mod[0],ci[i][1]=ci[i-1][1]*bas%mod[1];
	for(int i=1;i<=n;i++)
	{
		d[st[i]][0]=bas+s[st[i]];
		d[st[i]][1]=bas+s[st[i]];
		for(int j=1;j<len[i];j++)
		{
			d[j+st[i]][0]=(d[j+st[i]-1][0]*bas+s[j+st[i]])%mod[0];
			d[j+st[i]][1]=(d[j+st[i]-1][1]*bas+s[j+st[i]])%mod[1];
		}
	}
	for(int i=1;i<=qq;i++)
	{
		scanf("%s",c);
		LL t1=0,t2=0;
		len2[i]=strlen(c);
		for(int j=0;j<len2[i];j++)
		{
			t1=(t1*bas+c[j])%mod[0];
			t2=(t2*bas+c[j])%mod[1];
		}
		hah[i][0]=t1,hah[i][1]=t2;
	}
	for(int i=1;i<=qq;i++)num[i]=i;
	sort(num+1,num+qq+1,cmp);
	for(int i=1;i<=qq;i++)
	{
		int j=i;
		while(j<n&len2[num[j+1]]==len2[num[i]])j++;
		hhh(len2[num[i]],i,j);
	}
	for(int i=1;i<=qq;i++)printf("%d\n",ans[i]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值