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;
}