0
点赞
收藏
分享

微信扫一扫

2017 ACM-ICPC 亚洲区(西安赛区)网络赛 I. Barty's Computer(哈希)


Barty have a computer, it can do these two things.

  1. Add a new string to its memory, the length of this string is even.
  2. For given 44 strings a,b,c,da,b,c,d, find out how many strings that can be product by a+s1+b+c+s2+da+s1+b+c+s2+d, and |a| + |s1| + |b| = |c| + |s2| + |d|∣a∣+∣s1∣+∣b∣=∣c∣+∣s2∣+∣d∣. |s|∣s∣means the length of string ss, s1s1 and s2s2can be any string, including ​​""​​.

Please help your computer to do these things.

Input Format

Test cases begins with T(T \le 5)T(T≤5).

Then TT test cases follows.

Each test case begins with an integer Q(Q \le 30000)Q(Q≤30000).

Then QQ lines,

1 s: add a new string ss to its memory.

2 a b c d: find how many strings satisfying the requirement above.

\sum |s| + |a| + |b| + |c| + |d| \le 2000000∑∣s∣+∣a∣+∣b∣+∣c∣+∣d∣≤2000000.

Output Format

For type 22 query. Output the answer in one line.

样例输入复制


1 10 1 abcqaq 1 abcabcqaqqaq 2 ab bc qa aq 2 a c q q 1 abcabcqaqqwq 2 ab bc qa aq 2 a c q q 1 abcq 2 a c q q 2 a b c q


样例输出复制


1 2 1 3 3 1


题目来源

​​2017 ACM-ICPC 亚洲区(西安赛区)网络赛​​

 

题意:

Q次操作,操作有两种:

1 str : 表示增加一个字符串str(长度一定是偶数)

2 a b c d : 询问有多少个字符串满足str = a + s1 + b + c + s2 + d, 且|a|+|s1|+|b| = |c|+|s2|+|d|, s1, s2可以是任意字符串,空的也可以。

分析:

由于|a|+|s1|+|b| = |c|+|s2|+|d|, 所以我们可以得出|a|+|s1|+|b| 和 |c|+|s2|+|d|分别恰好为某个字符串的前一半和后一半。即字符串满足前一半的前缀是a, 后缀是b, 后一半的前缀是c, 后缀是d即可。

怎么快速判断一个串的前缀或后缀是否是某一个字符串呢?我们可以用hash, 这样就能以O(1)复杂度判断某个串是否满足,所以每次询问枚举所有串即可。(字典树也可以)。

双Hash防止被卡

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const ULL base1=131;
const LL base2=131;
const LL mod=1e9+7;
const LL N=1e6+10;
ULL hash1[N],hasha1[N],hashb1[N],hashc1[N],hashd1[N];
ULL power1[N];
LL hash2[N],hasha2[N],hashb2[N],hashc2[N],hashd2[N];
LL power2[N];
void init()
{
power1[0]=1;
for(int i=1; i<=N; i++)
{
power1[i]=power1[i-1]*base1;
}

power2[0]=1;
for(int i=1; i<=N; i++)
{
power2[i]=(power2[i-1]*base2)%mod;
}
}

void initHash(int l,int r,ULL h1[],LL h2[],char s[])
{

int i=1;
for(int j=l; j<=r; j++,i++)
{
h1[j]=h1[j-1]*base1+(s[i]-'a');
h2[j]=(((h2[j-1]%mod)*(base2%mod))%mod+(s[i]-'a')%mod)%mod;
}
}
bool judgeHash(int l,int r,int x,int y,ULL h1[],LL h2[])
{

ULL temp1=hash1[r]-hash1[l-1]*power1[r-l+1];
LL temp2=(hash2[r]-((hash2[l-1]%mod)*(power2[r-l+1]%mod))%mod+mod)%mod;

//ULL temp3=h1[y]-h1[x-1]*power1[y-x+1];
//LL temp4=(h2[y]-((h2[x-1]%mod)*(power2[y-x+1]%mod))%mod+mod)%mod;
if(temp1==h1[y]&&temp2==h2[y])
return 1;
else
return 0;

}
char a[N],b[N],c[N],d[N],str[N];
vector<int>len;

int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
len.clear();
int n;
scanf("%d",&n);
int totlen=0;
while(n--)
{
int op;
scanf("%d",&op);

if(op==1)
{
scanf("%s",str+1);
int temp=strlen(str+1);
len.push_back(temp);
totlen+=temp;
initHash(totlen-temp+1,totlen,hash1,hash2,str);
}
else
{
scanf("%s %s %s %s",a+1,b+1,c+1,d+1);
int alen=strlen(a+1);
int blen=strlen(b+1);
int clen=strlen(c+1);
int dlen=strlen(d+1);
initHash(1,alen,hasha1,hasha2,a);
initHash(1,blen,hashb1,hashb2,b);
initHash(1,clen,hashc1,hashc2,c);
initHash(1,dlen,hashd1,hashd2,d);
int curlen=0;
LL ans=0;
for(int j=0; j<len.size(); j++)
{
curlen+=len[j];

if(alen+blen>len[j]/2||clen+dlen>len[j]/2)
continue;

if(judgeHash(curlen-len[j]+1,curlen-len[j]+alen,1,alen,hasha1,hasha2)==0)
continue;
if(judgeHash(curlen-len[j]/2-blen+1,curlen-len[j]/2,1,blen,hashb1,hashb2)==0)
continue;
if(judgeHash(curlen-len[j]/2+1,curlen-len[j]/2+clen,1,clen,hashc1,hashc2)==0)
continue;
if(judgeHash(curlen-dlen+1,curlen,1,dlen,hashd1,hashd2)==0)
continue;

ans++;
}

printf("%lld\n",ans);

}
}
}
return 0;
}

 

举报

相关推荐

0 条评论