分析
题意就是不断跳到下一个字母问总共跳的长度有多长,
首先用一个变量存下初始位置,(以下使用0开头,方便后面统计)
但显然暴力跳会T飞,必然存在循环节,长度为字母个数所贡献的答案为字符串长度
那么考虑高精度,求出有多少个循环节贡献的字符串长度,这里可以将星号视为所有字母,
关键就是余数部分,考虑用vector存下每个字母的位置,以及该位置下对应vector的位置,
那直接vector下标往后移余数位就可以了呀。
代码
#include <cstdio> #include <cstring> #include <cctype> #include <vector> #include <algorithm> #define rr register using namespace std; const int mod=998244353,N=100011; char S[N],T[N]; vector<int>K[27]; int Test,loc[N][2],c[N],len,LEN,ans; inline void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;} inline signed doit(int l,int r,int C1,int C2){ rr int g=0,s=0,tot=0,cho; for (rr int i=l;i<=r;++i) c[i-l+1]=T[i]^48; for (cho=r-l+1;!c[cho];--cho); --c[cho]; for (rr int i=cho+1;i<=r-l+1;++i) c[i]=9; for (rr int i=l;i<=r;++i,g=s%C1) s=g*10+c[i-l+1],c[++tot]=s/C1; s=0; for (rr int i=tot;i;--i) s+=c[i]*C2,c[i]=s%10,s/=10; for (rr int i=1;i<=tot;++i) s=(s*10ll+c[i])%mod; Mo(ans,s); return g; } signed main(){ scanf("%s%d",S,&Test),len=strlen(S); for (rr int i=0;i<len;++i) K[S[i]^96].push_back(i),loc[i][0]=K[S[i]^96].size()-1; for (rr int i=0;i<len;++i) K[0].push_back(i),loc[i][1]=i; for (rr int LEN;Test;--Test){ scanf("%s",T),LEN=strlen(T),ans=0; rr int l=0,r=0,beg=len-1,flag=1; for (rr int f=0,now;l<LEN;l=++r){ if (T[l]=='*') T[l]=96,f=1; else f=0; rr int G=T[l]^96,siz=K[G].size(),nxt; if (!siz) {flag=0; break;} if (l+1<LEN&&isdigit(T[l+1])) for (;r+1<LEN&&isdigit(T[r+1]);++r); if (K[G][siz-1]<=beg) nxt=K[G][0]; else nxt=*upper_bound(K[G].begin(),K[G].end(),beg); if (beg<nxt) Mo(ans,nxt-beg),beg=nxt; else Mo(ans,len-beg+nxt),beg=nxt; if (l<r){ if (now=doit(l+1,r,siz,len)){ nxt=K[G][(loc[beg][f]+now)%siz]; if (beg<nxt) Mo(ans,nxt-beg),beg=nxt; else Mo(ans,len-beg+nxt),beg=nxt; } } } if (!flag) printf("-1\n"); else printf("%d\n",ans); } return 0; }