2020牛客NOIP赛前集训营-提高组(第二场)前缀-C(字符串,序列自动机)

题目描述

Statement

在这里插入图片描述

Solution

  • 有序列自动机思想
  • 如图在这里插入图片描述
  • 思路就是用 r e s res res处理循环的整个字符串,余数为 r e m rem rem
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10,A=27,mod=998244353;
char sc[N];
int M1(int x){return x>=mod?x-mod:x;}
int M2(int x){return x<0?x+mod:x;}
int n,m,T,s[A][N],i,j,l,r,v,x,rem,ans,res,nxt,cur;
int main()
{
	scanf("%s",sc+1);
	n=strlen(sc+1);
	for(i=1;i<=n;i++)
	{
		for(j=0;j<A;j++)
			s[j][i]=s[j][i-1];
		++s[sc[i]-'a'+1][i];
		++s[0][i];//*	
	}//sequence automata
	scanf("%d",&T);
	while(T--)
	{
		bool flag=0;
		scanf("%s",sc+1);
		m=strlen(sc+1);
		cur=1,ans=0;
		for(i=1;i<=m;i=r+1)
		{
			v=(sc[i]=='*')?0:sc[i]-'a'+1;
			x=s[v][n];//一次循环所有v个数
			if(!x){flag=1;break;}//不存在(未出现v)
			r=i,res=0,rem=1;//数字右边界,商,余数
			if(i+1<=m&&sc[i+1]>='0'&&sc[i+1]<='9')
			{
				l=i+1,rem=0;//数字左边界 
				while(r+1<=m&&sc[r+1]>='0'&&sc[r+1]<='9') ++r;
				for(i=l;i<=r;i++)
					rem=10*rem+(sc[i]-'0'),
					res=(10ll*res+(rem/x))%mod,
					rem%=x;//高精除低精
				res=1ll*res*n%mod;	
				if(!rem) rem=x,res=M2(res-n);	
			}
			if(s[v][n]-s[v][cur-1]<rem)
				res=M1(res+n-cur+1),rem-=s[v][n]-s[v][cur-1],cur=1;
			nxt=lower_bound(s[v]+cur,s[v]+n+1,s[v][cur-1]+rem)-s[v]+1;
			res=M1(res+nxt-cur);
			cur=nxt,ans=M1(ans+res);	
		}
		if(flag) puts("-1");
		else printf("%d\n",ans);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值