正规题解传送门 : https://zyqn.tech/?p=3163
但是我们发现n只有2000,于是可以建出trie树然后愉快的bitset去搞。
直接对于trie上每个节点开个bitset空间爆炸。但是有很多是重复的,所以我们想虚树一样建,每个节点只存一个link指针。
代码 :
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define eps 1e-9 #define LL long long using namespace std; #define int int inline int Max(int a,int b) {return a>b?a:b;} inline int Min(int a,int b) {return a<b?a:b;} inline int Sqr(int a) {return a*a;} inline int Abs(int a) {return a>0?a:-a;} #undef int #define MAXN 2000006 int n,m,ans; bitset<2005> x,pol[100005];int tot; char s[MAXN]; struct Trie{ int tra[MAXN][27],lk[MAXN],cnt; void Init() { memset(tra,0,sizeof(tra)); cnt=1; } void Build(int v) { int fr=0; for(int i=0;i<27;i++) { if(!tra[v][i]) continue; Build(tra[v][i]); if(!fr) lk[v]=lk[tra[v][i]],fr=1; else if(fr==1) { tot++;pol[tot]=pol[lk[v]]; pol[tot]|=pol[lk[tra[v][i]]]; lk[v]=tot;fr=2; } else pol[lk[v]]|=pol[lk[tra[v][i]]]; } } void Insert(int k,char *s,int len) { int now=1; for(int i=0;i<len;i++) { if(!tra[now][s[i]-'a']) now=tra[now][s[i]-'a']=++cnt; else now=tra[now][s[i]-'a']; } if(!lk[now]) lk[now]=++tot; pol[lk[now]][k]=1; } int Patten(char *s,int len) { int now=1; for(int i=0;i<len;i++) { if(!tra[now][s[i]-'a']) return 0; now=tra[now][s[i]-'a']; } return lk[now]; } }hd,bk; inline void Updata(int n) { for(int i=0;i<n;i++) s[i]=((s[i]-'a'+ans)%26)+'a'; } int main() { hd.Init();bk.Init(); scanf("%d",&n); for(int len,i=1;i<=n;i++) { scanf("%s",s); len=strlen(s); hd.Insert(i,s,len); reverse(s,s+len); bk.Insert(i,s,len); } hd.Build(1); bk.Build(1); scanf("%d",&m); for(int len,i=1;i<=m;i++) { x.set(); scanf("%s",s); len=strlen(s); Updata(len); x&=pol[hd.Patten(s,len)]; scanf("%s",s); len=strlen(s); reverse(s,s+len); Updata(len); x&=pol[bk.Patten(s,len)]; ans=x.count(); printf("%d ",ans); } return 0; }