题目大意
给定一个模板串T,字符集为
有q个询问,每次给出一个串
1≤|T|≤105,∑|S|≤105,q≤103
题目分析
对T串构造后缀自动机,然后拿询问串在上面跑。
对于询问串的一个位置
既然字符集大小为4,考虑使用
时间复杂度
代码实现
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N=100050;
const int W=4;
const int S=1<<W;
const int V=N<<1;
int sum[N][S],pre[N];
int pur,cor;
namespace SAM
{
struct node
{
int prt,len,pos;
int nxt[W];
}sam[V];
int tot,root;
int newnode()
{
++tot,memset(sam[tot].nxt,0,sizeof sam[tot].nxt),sam[tot].prt=sam[tot].len=sam[tot].pos=0;
return tot;
}
void init(){tot=0,root=newnode();}
int insert(int lst,int c,int ps)
{
int np=newnode(),p=lst,q;
for (sam[np].len=sam[p].len+1,sam[np].pos=ps;p&&!sam[p].nxt[c];p=sam[p].prt) sam[p].nxt[c]=np;
if (!p) sam[np].prt=root;
else if (sam[q=sam[p].nxt[c]].len==sam[p].len+1) sam[np].prt=q;
else
{
int nq=newnode();
sam[nq]=sam[q],sam[np].prt=sam[q].prt=nq;
for (sam[nq].len=sam[p].len+1;p&&sam[p].nxt[c]==q;p=sam[p].prt) sam[p].nxt[c]=nq;
}
return np;
}
int match(int &p,int c,int &len)
{
int ret=0;
for (;p&&!sam[p].nxt[c];p=sam[p].prt,len=sam[p].len);
p=p?p:root;
if (sam[p].nxt[c]) p=sam[p].nxt[c],++len;
for (int s=0,r=sam[p].pos,l=r-len;s<S;++s)
if (!((s^pur)&cor)) ret+=(r?sum[r-1][pre[r]^s]:(pre[r]^s?0:1))-(l-1>=0?sum[l-1][pre[r]^s]:(pre[r]^s?0:(!l?1:0)));
return ret;
}
};
char T[N],str[N],L[10];
int id[26];
int n,m,q;
int main()
{
id[0]=0,id[2]=1,id[19]=2,id[6]=3;
freopen("pattern.in","r",stdin),freopen("pattern.out","w",stdout);
scanf("%d",&q),scanf("%s",T),n=strlen(T),SAM::init();
sum[0][0]=1;
for (int i=0,lst=SAM::root;i<n;++i)
{
lst=SAM::insert(lst,id[T[i]-'A'],i);
if (i) for (int s=0;s<S;++s) sum[i][s]=sum[i-1][s];
++sum[i][pre[i]=(i?pre[i-1]:0)^(1<<id[T[i]-'A'])];
}
for (LL ans;q--;printf("%lld\n",ans))
{
scanf("%s",str),m=strlen(str);
scanf("%s",L),pur=cor=0;
for (int i=0;L[i]!='\0';++i)
if ('A'<=L[i]&&L[i]<='Z') pur|=1<<id[L[i]-'A'],cor|=1<<id[L[i]-'A'];
else cor|=1<<id[L[i]-'a'];
ans=0;
for (int i=0,lst=SAM::root,l=0;i<m;++i) ans+=SAM::match(lst,id[str[i]-'A'],l);
}
fclose(stdin),fclose(stdout);
return 0;
}