【JZOJ6216】【20190614】序列计数
2024-09-20 04:58:14
题目
一个长为\(N\)的串\(S\),\(M\)询问区间\([l,r]\)不同的子串个数,字符集为$ C $
\(N ,M \le 10^5 \ , \ C \le 10\)
题解
这题非常套路。。。
part 1
设\(dp_{i,j}\)为考虑i,字符j结尾的子串个数,考虑\(S_i=c\)
\[\begin{align}
&dp_{i,j} = dp_{i,j}\\
&dp_{i,c} = \sum_{j} dp_{i-1,j} + 1
\end{align}
\]part 2
设一个大小\(C+1\)的矩阵,写出转移矩阵
\[A_i = \begin{pmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
1 & 1 & 1 & 1\\
0 & 0 & 0 & 1\\
\end{pmatrix}
\]它的逆矩阵
\[B_i = \begin{pmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
-1 & -1 & -1 & -1\\
0 & 0 & 0 & 1\\
\end{pmatrix}
\]只需要预处理出矩阵的前缀即可
part 3
左乘一个A相当于某一行变为所有行的和,可以维护一列的和
右乘一个B相当于其它列减去某一列,可以维护整体减法标记
统计答案也可以直接利用维护的东西,具体见代码
时间复杂度$ O((N+M)C) $
#include<bits/stdc++.h>
using namespace std;
const int N=500010,mod=1e9+7;
int n,m,f1[N][11],f2[N][11];
char s[N],ps[1000000],*pp=ps;
void flush(){fwrite(ps,1,pp-ps,stdout);pp=ps;}
void push(char x){if(pp==ps+1000000)flush();*pp++=x;}
void write(int x){
static int sta[20],top;
if(!x){push('0');push('\n');return;}
while(x)sta[++top]=x%10,x/=10;
while(top)push(sta[top--]^'0');
push('\n');
}
void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;}
void dec(int&x,int y){x-=y;if(x<0)x+=mod;}
struct Mat{
int c[11][11],s[11],d[11],D;
void init(){for(int i=0;i<11;++i)c[i][i]=s[i]=1;}
void plus(int I){
for(int i=0;i<11;++i){
int t=c[I][i];c[I][i]=s[i];
s[i]=(2*s[i]%mod-t+mod)%mod;
}
}
void minus(int I){
for(int i=0;i<11;++i){
int t=d[i];d[i]=c[i][I];
c[i][I]=(2*d[i]%mod-t+mod)%mod;
}
}
void print(int typ){
for(int i=0;i<11;++i,puts(""))
for(int j=0;j<11;++j){
int t=typ?(c[i][j]-d[i]+mod)%mod:c[i][j];
if(mod-t<t)t=t-mod;
printf("% 2d ",t);
}
puts("\n");
if(!typ)for(int i=0;i<11;++i)printf("%d ",s[i]);
puts("\n");
}
}A,B;
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
scanf("%s%d",s+1,&m);n=strlen(s+1);
A.init(),B.init();f2[0][10]=1;
for(int i=1;i<=n;++i){
A.plus(s[i]-'a');
B.minus(s[i]-'a');
for(int j=0;j<11;++j){
f1[i][j]=A.s[j];
f2[i][j]=(B.c[j][10]-B.d[j]+mod)%mod;
}
}
for(int i=1,l,r,ans;i<=m;++i){
scanf("%d%d",&l,&r);
ans=0;for(int j=0;j<11;++j)inc(ans,1ll*f1[r][j]*f2[l-1][j]%mod);
if(!ans)ans=mod-1;else ans--;write(ans);
}
return flush(),0;
}
最新文章
- three.js立方体
- java 极光推送
- UzysAssetsPickerController中文化
- C# HttpHelper 采集
- Win7 下以管理员身份运行批处理文件,切换JDK版本
- java数据结构和算法------希尔排序
- swift:创建九宫格
- Spring MVC page render时jsp中元素相对路径的解决办法
- A simple brute force problem.
- pstree命令
- 建立Go工作环境
- 【WCF】服务并发中的“可重入模式”
- Robot framework的介绍
- 本地存储 web storage
- python8 字符串操作
- js正则表达式 数字和小数点 非负数 保留两位小数点
- Oracle 数据表误删恢复 Flashback
- c++将lambda作为callback函数
- ubuntu 安装 mysql 的正确姿势
- web前端开发浅析
热门文章
- 如何配置这个maven仓库的源http://mvnrepository.com/repos
- 使用canvas实现360水球波动
- .Net Core SignalR+LayUi(1)-简单入门
- 无法定位 Local Database Runtime 安装。请验证 SQL Server Express 是否正确安装以及本地数据库运行时功能是否已启用。
- python基础知识(七)---数据类型补充、";雷区";、编码
- 珠宝juelrye宝石
- Jmeter学习笔记(二十)——后置处理器XPath Extractor使用
- zookeeper介绍(4)zookeeper的完整分布式
- 移动端H5长按事件 vue自定义指令
- C++中string的实现原理