满足要求的区间个数,多组询问
明显枚举每个区间算贡献,
对于每个位置求前面26个字母首次出现的位置,
枚举区间右端点r,枚举区间左端点l,[l,r]之间不能有第r+1个字母
O(n*26)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<map>
using namespace std;
const int N=1e6+10;
const int M=1e4+10;
int s[30];
short mp[1<<26],tot;
int ans[M];
void init(){
memset(s,0,sizeof(s));
for(int i=0;i<26;i++){
s[i]=1<<i;
}
}
int up(int aa[N],int l1,int bb[N],int l2){
for(int i=0;i<l1;i++){
if(aa[i]==bb[0])continue;
bb[l2++]=aa[i];
}
return l2;
}
void up1(int aa[N],int l1,int next){
int mask=0;
for(int i=0;i<l1;i++){
if(aa[i]==next)break;
mask|=s[aa[i]];
ans[mp[mask]]++;
}
}
char ss[N],tt[30];
int fun(){
int n=strlen(tt);
int mask=0;
for(int i=0;i<n;i++){
mask|=s[tt[i]-'a'];
}
return mask;
}
int aa[M];
int sta[2][N],top[2];
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
init();
while(scanf("%s",ss)!=EOF){
int n=strlen(ss),m=1;
for(int i=1;i<n;i++){
if(ss[i]==ss[i-1])continue;
else ss[m++]=ss[i];
}
n=m;
int q;scanf("%d",&q);
memset(mp,0,sizeof(mp));
memset(ans,0,sizeof(ans));
tot=0;
for(int i=0;i<q;i++){
scanf("%s",tt);
aa[i]=fun();
if(mp[aa[i]]==0){
mp[aa[i]]=++tot;
}
}
top[0]=top[1]=0;
int id=0;
for(int i=0;i<n;i++){
top[id]=1;
sta[id][0]=ss[i]-'a';
top[id]=up(sta[id^1],top[id^1],sta[id],top[id]);
if(i+1<n)up1(sta[id],top[id],ss[i+1]-'a');
else up1(sta[id],top[id],-1);
id^=1;
}
for(int i=0;i<q;i++){
printf("%d\n",ans[mp[aa[i]]]);
}
}
return 0;
}