Description
有一个字符串组成的集合,初始为空集,有 q q 个操作,操作分两种:
在集合中加入字符串 s s ,长度为偶数
2 a b c d: 2 a b c d : 问集合中有多少字符串可以被表示成 a+s1+b+c+s2+d a + s 1 + b + c + s 2 + d 的形式且 |a|+|s1|+|b|=|c|+|s2|+|d| | a | + | s 1 | + | b | = | c | + | s 2 | + | d | ,其中 s1,s2 s 1 , s 2 为任意字符串,也可以是空串
Input
第一行一整数 T T 表示用例组数,每组用例首先输入一整数表示操作数,之后 q q 行每行输入一个操作
Output
对于每个查询操作输出结果
Sample Input
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
Sample Output
1
2
1
3
3
1
Solution
把集合中每个字符串分成长度相同的两部分,把这两部分字符串的前缀和后缀都 hash h a s h 后存起来,对于输入的 a,b,c,d a , b , c , d ,只要该字符串的前半部分的前缀后缀 hash h a s h 值分别与 a,b a , b 的 hash h a s h 值相同,后半部分的前缀后缀 hash h a s h 值分别与 c,d c , d 的 hash h a s h 值相同则该字符串满足条件
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=30005,maxm=2000005;
#define mod 1000000007
vector<int>al[maxn],ar[maxn],bl[maxn],br[maxn];
int T,q,len[maxn],res;
char s[maxm],a[maxm],b[maxm],c[maxm],d[maxm];
int lhash(char *s,int n)
{
int ans=0;
for(int i=0;i<n;i++)ans=(26ll*ans+s[i]-'a')%mod;
return ans;
}
int rhash(char *s,int n)
{
int ans=0;
for(int i=n-1;i>=0;i--)ans=(26ll*ans+s[i]-'a')%mod;
return ans;
}
int main()
{
scanf("%d",&T);
while(T--)
{
for(int i=0;i<res;i++)al[i].clear(),ar[i].clear(),bl[i].clear(),br[i].clear();
res=0;
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
scanf("%s",s);
int n=strlen(s),temp=0;
for(int i=0;i<n/2;i++)
{
temp=(26ll*temp+s[i]-'a')%mod;
al[res].push_back(temp);
}
temp=0;
for(int i=n/2-1;i>0;i--)
{
temp=(26ll*temp+s[i]-'a')%mod;
ar[res].push_back(temp);
}
temp=0;
for(int i=n/2;i<n;i++)
{
temp=(26ll*temp+s[i]-'a')%mod;
bl[res].push_back(temp);
}
temp=0;
for(int i=n-1;i>=n/2;i--)
{
temp=(26ll*temp+s[i]-'a')%mod;
br[res].push_back(temp);
}
len[res]=n/2;
res++;
}
else
{
scanf("%s%s%s%s",a,b,c,d);
int la=strlen(a),lb=strlen(b),lc=strlen(c),ld=strlen(d);
int ans=0;
for(int i=0;i<res;i++)
{
if(la+lb>len[i]||lc+ld>len[i])continue;
if(lhash(a,la)==al[i][la-1]&&rhash(b,lb)==ar[i][lb-1]&&lhash(c,lc)==bl[i][lc-1]&&rhash(d,ld)==br[i][ld-1])ans++;
}
printf("%d\n",ans);
}
}
}
return 0;
}