Description
GAL发现了N个特殊的字母序列,由小写字母组成。小L认为,对于两个字符串s1,s2,若s1是某个特殊序列的前缀,s2是该特殊序列的后缀,则称s1,s2被这个序列拥有。
现在小L给出M对s1,s2,对于每对字符串,问它们被几个特殊序列拥有。
Input
第1行一个整数N。
接下来N行,每行一个字符串,代表N个特殊序列。
第N+2行一个整数M。
接下来M行每行一对s1,s2用空格隔开。S1,s2是经过加密的。
设上一问的答案为lastans。解密方法是将s1,s2所有字母向后移动lastans个单位,这时你要把小写字母表当作一个环,比如z的下一个字母是a。
Output
对于每次询问操作,输出一个非负整数表示答案。
Sample Input
3
aaaaa
abacabaa
avtobus
6
a a
y yy
yy y
zzzzz zzzz
zazb bzaz
abac a
aaaaa
abacabaa
avtobus
6
a a
y yy
yy y
zzzzz zzzz
zazb bzaz
abac a
Sample Output
2
2
1
1
0
1
2
1
1
0
1
HINT
设N个特殊序列总长为L1,所有M组询问总长为L2。L1,L2<=2000000.N<=2000,M<=100000
题解:
把每个串正着hash一遍,再反着hash一遍。用vector存一下hash值。
每次暴力查询即可。
然后跑了17秒,卡过。。。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define M 2000010
#define P 1000000007
using namespace std;
string s[2010];
char ch[M],a[M],b[M];
vector<unsigned long long>l[2010],r[2010];
int len[2010],n,m,ans;
void hash(){
for (int i=1;i<=n;i++){
unsigned long long x(17),x2(17);
for (int j=0;j<len[i];j++){
x=x*P+s[i][j];l[i].push_back(x);
}
for (int j=0;j<len[i];j++){
x2=x2*P+s[i][len[i]-j-1];r[i].push_back(x2);
}
}
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%s",&ch);len[i]=strlen(ch);
for (int j=0;j<len[i];j++) s[i]+=ch[j];
}
hash();scanf("%d",&m);ans=0;
for (int i=1;i<=m;i++){
unsigned long long aa(17),bb(17);
int len1,len2;
scanf("%s",&a);len1=strlen(a);
for (int j=0;j<len1;j++) a[j]=(a[j]-'a'+ans)%26+'a';
for (int j=0;j<len1;j++) aa=aa*P+a[j];
scanf("%s",&b);len2=strlen(b);
for (int j=0;j<len2;j++) b[j]=(b[j]-'a'+ans)%26+'a';
for (int j=0;j<len2;j++) bb=bb*P+b[len2-j-1];ans=0;
for (int j=1;j<=n;j++)
if (l[j][len1-1]==aa&&r[j][len2-1]==bb) ans++;
printf("%d\n",ans);
}
}