Barty have a computer, it can do these two things.
- Add a new string to its memory, the length of this string is even.
- 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;
}










