【jzoj5084】【GDOI2017第四轮模拟day1】【子串】【后缀数组】
来源:互联网 发布:mac 编译安装php fpm 编辑:程序博客网 时间:2024/06/09 23:55
题目大意
YJC最近写了一篇关于子串的论文。CJY看他那么喜欢子串,决定出一道题考考他。
CJY给出了一个字符串s,令s[l~r]表示s中区间[l,r]构成的子串,下标从1开始。他向YJC提出了许多询问,每次询问给了四个数i,j,k,l,求LCP(s[i~k],s[j~l]),即每次询问两个子串的最长公共前缀。YJC很轻松地解决了这个问题。CJY表示很不爽,于是他改变了一下问题,让YJC求所有合法的询问的答案的和,即设n=|S|,求
。YJC发现现在自己不会做了,于是他来向你求助。因为这个数可能很大,你只需要告诉他答案mod 998244353的值即可。
解题思路
先做一遍sa,对height前后做一次单调栈,分别是递增和不递减,求出点的数量和sa和,推出公式后可以直接得解,先把含∑ 的式子求出来,用等差数列求和公式前缀平方和公式求和即可。注意把答案乘二后加上自己乘自己的情况。
code
#include<cstdio>#include<cstring>#include<algorithm>#define LL long long#define fo(i,j,k) for(LL i=j;i<=k;i++)#define fd(i,j,k) for(LL i=j;i>=k;i--)using namespace std;LL const mn=5*1e5+9,mo=998244353;LL n,m,a[2][mn],sa[mn],cnt[mn],h[mn],st[mn],f[mn],g[mn],suml[mn],sizel[mn];LL *rank=a[0],*ord=a[1];char s[mn];void sort(){ fo(i,1,m)cnt[i]=0; fo(i,1,n)cnt[rank[i]]++; fo(i,1,n)cnt[i]+=cnt[i-1]; fd(i,n,1)sa[cnt[rank[ord[i]]]--]=ord[i];}LL diff(LL x,LL y,LL z){ return (ord[x]!=ord[y])||(ord[x+z]!=ord[y+z]);}int main(){ //freopen("substring.in","r",stdin); //freopen("substring.out","w",stdout); freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%s",s+1);n=strlen(s+1); fo(i,1,n)rank[i]=s[i]-'a'+1,ord[i]=i;m=26; sort(); for(LL w=1,p=0;p!=n;w<<=1){ p=0;fo(i,n-w+1,n)ord[++p]=i; fo(i,1,n)if(sa[i]>w)ord[++p]=sa[i]-w; sort();swap(rank,ord);rank[sa[1]]=p=1; fo(i,2,n)rank[sa[i]]=p+=diff(sa[i],sa[i-1],w); m=p; } for(LL i=1,j,p=0;i<=n;h[rank[i]]=p,i++) for(j=sa[rank[i]-1],p=(p)?p-1:p;s[i+p]==s[j+p];p++); LL ans=0; fo(i,2,n){ LL tmp=0,tmp2=0; while(st[0]&&(st[st[0]]>h[i]))tmp+=f[st[0]],tmp2+=g[st[0]],st[0]--; st[++st[0]]=h[i]; suml[i]=f[st[0]]=(tmp+sa[i-1])%mo; sizel[i]=g[st[0]]=tmp2+1; } st[0]=0; fd(i,n,2){ LL tmp=0,tmp2=0; while(st[0]&&(st[st[0]]>=h[i]))tmp+=f[st[0]],tmp2+=g[st[0]],st[0]--; st[++st[0]]=h[i]; f[st[0]]=(tmp+sa[i])%mo; g[st[0]]=tmp2+1; LL l=h[i],sumr=f[st[0]],sizer=g[st[0]]; ans=(ans+((l*(l+1)/2-l*(l+1)*(2*l+1)/6)/2+l*(n+1-l)*(n+1-l)-l*l*(l+1)/2)%mo*(sizel[i]*sizer%mo) -(l*(n+1-l)%mo)*((suml[i]*sizer+sumr*sizel[i])%mo)+(l*(l+1)/2%mo)*((((n+1)*sizel[i]-suml[i])*sizer+((n+1)*sizer-sumr)*sizel[i])%mo) +l*suml[i]%mo*sumr)%mo; } ans<<=1; fo(i,1,n)ans=(ans+(i*(i+1)/2-i*(i+1)*(2*i+1)/6)/2+i*i*(i+1)/2)%mo; printf("%lld",ans); return 0;}
0 0
- 【jzoj5084】【GDOI2017第四轮模拟day1】【子串】【后缀数组】
- 【GDOI2017第四轮模拟day1】数列
- 【GDOI2017第四轮模拟day1】数列
- 【jzoj5086】【GDOI2017第四轮模拟day1】【数列】【搜索】
- [JZOJ5084]子串
- jzoj 5085. 【GDOI2017第四轮模拟day1】游戏 sg函数+线性基+bitset
- jzoj 5086. 【GDOI2017第四轮模拟day1】数列 搜索+meet in the middle
- 【jzoj5085】【GDOI2017第四轮模拟day1】【游戏】 【sg函数】【线性基】
- GDOI2017第四轮模拟总结
- GDOI2017模拟第四轮总结
- 【GDOI2017模拟9.10】子串
- 【GDOI2017第四轮模拟day2】叶片
- 【jzoj5089】【GDOI2017第四轮模拟day2】【叶片】
- 【GDOI2017第四轮模拟day2】绝版题
- jzoj 4690. 【GDOI2017模拟8.12】字符串 后缀数组+RMQ
- jzoj 4683. 【GDOI2017模拟8.11】矩阵 后缀数组+哈希表
- 4774. 【GDOI2017模拟9.10】子串
- 【GDOI2017第二轮模拟day1】最长路径
- Webservice认识
- Web前端上万字的知识总结
- Convolutional Neural Networks
- Frequency Filters-1
- Oracle之PL/SQL学习笔记
- 【jzoj5084】【GDOI2017第四轮模拟day1】【子串】【后缀数组】
- eclipse(maven+springmvc+spring+mybatis)(下)
- RecyclerView的数据更新问题
- TP5微信开发地址验证中的配置失败或者token验证失败的解决办法
- linux 下的绘图软件Visio——流程图,矢量图
- ubuntu 下安装MySQL-python
- 【机器学习基础】非线性变换
- ServletContext简介
- iframe 自适应全屏