公共子序列_NOI导刊2011提高(03)题
这道题有点坑人啊~
首先,它需要取模,模数是100000000;(窝在这里死了好久好久,看了别人的代码才发现这一点)
然后我发现题解中没有序列自动机的方法,于是就来一发
首先,虽然序列自动机在定义上与后缀自动机、回文自动机等听起来比较高大上的算法同属于自动机的范畴,但它仅仅是个**普及-**算法
为何?因为你不学都有可能会(逃)
自动机,就是把一个字符串通过某种关系构成一幅有向无环图,这样可以方便我们进行图上dp
序列自动机的构造方法:
设一个字符集S,nxt[i][j]表示第i个位置往后第一个j元素出现的位置;
这个nxt数组可以O(n)的求出来,可以自行验证;
for(int i=n-;i>=;--i){
for(int j=;j<=;++j) nxt[i][j]=nxt[i+][j];
nxt[i][s[i+]-'a'+]=i+;
}
她能干什么事情呢?(应用)
1.判断是否是原字符串的子序列
当我们构造出nxt数组之后,可以贪心的寻找子序列;
2.求一个序列的子序列个数;(可以限定序列的长度)
我们在DAG上跑拓扑DP,f[v][j]表示从1~v寻找j个元素的方案数;
显然的:f[v][j]+=f[u][j-1];
#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
#define dec(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
char s[3010];
int nxt[3010][40];
int n,m;
long long f[3010][3010];
int rudu[3010];
const int p=998244353;
queue<int> qwq;
void tp()
{
qwq.push(0);
f[0][0]=1;
while(qwq.size()){
int u=qwq.front();
qwq.pop();
inc(i,0,25){
if(!nxt[u][i]) continue;
inc(j,0,u) f[nxt[u][i]][j+1]=(f[nxt[u][i]][j+1]+f[u][j])%p;
--rudu[nxt[u][i]];
if(rudu[nxt[u][i]]==0) qwq.push(nxt[u][i]);
}
}
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);cin>>m;
dec(i,n-1,0){
inc(j,0,25) nxt[i][j]=nxt[i+1][j];
nxt[i][s[i+1]-'a']=i+1;
inc(j,0,25) if(nxt[i][j]!=0) rudu[nxt[i][j]]++;
}
tp();
long long ans=0;
inc(i,1,n) ans=(ans+f[i][m])%p;
cout<<ans%p;
}
/*
addeade
3 aa
1
*/
#### 3.求两串的公共子序列个数(就是这道题)
#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
#define dec(i,a,b) for(register int i=a;i>=b;i--)
using namespace std;
char a[160],b[160],c[160];
int nxta[160][30],nxtb[160][30],nxtc[160][30];
long long f[160][160][160];
const int mod=100000000;
long long dfs(int x,int y,int z)
{
if(f[x][y][z]) return f[x][y][z];
inc(i,0,26){
if(nxta[x][i]&&nxtb[y][i]&&nxtc[z][i]){
f[x][y][z]=(f[x][y][z]+dfs(nxta[x][i],nxtb[y][i],nxtc[z][i]))%mod;
}
}
if(x||y||z) ++f[x][y][z];
return f[x][y][z]%mod;
}
int main()
{
int x,y,z;
int n;
cin>>n;
scanf("%s %s %s",a+1,b+1,c+1);
x=strlen(a+1); y=strlen(b+1); z=strlen(c+1);
dec(i,x-1,0){
inc(j,0,25) nxta[i][j]=nxta[i+1][j];
nxta[i][a[i+1]-'a']=i+1;
}
dec(i,y-1,0){
inc(j,0,25) nxtb[i][j]=nxtb[i+1][j];
nxtb[i][b[i+1]-'a']=i+1;
}
dec(i,z-1,0){
inc(j,0,25) nxtc[i][j]=nxtc[i+1][j];
nxtc[i][c[i+1]-'a']=i+1;
}
cout<<dfs(0,0,0)%mod;
}
4.求字符串的回文子序列个数
首先原串与反串都建一遍;
就相当于从左右端点向中间跑自动机;
显然:x+y<=n+1才会合法;
但要注意,我们只能统计偶数长度的字符串,而不能统计奇数个数的字符串;
因为我们永远都是两个两个地串;
long long Dfs(int x,int y){
if(f[x][y]) return f[x][y];
for(int i=1;i<=a;++i)
if(nxt1[x][i]&&nxt2[y][i]){
if(nxt1[x][i]+nxt2[y][i]>n+1) continue;
if(nxt1[x][i]+nxt2[y][i]<n+1) f[x][y]++;
f[x][y]=(f[x][y]+Dfs(nxt1[x][i],nxt2[y][i]))%mod;
}
return ++f[x][y];
}
公共子序列_NOI导刊2011提高(03)题的更多相关文章
- P1836 【数页码_NOI导刊2011提高(04)】
P1836 数页码_NOI导刊2011提高(04) 题目描述 一本书的页码是从1—n编号的连续整数:1,2,3,…,n.请你求出全部页码中所有单个数字的和,例如第123页,它的和就是1+2+3=6. ...
- 贪心—— P1809 过河问题_NOI导刊2011提高(01)
洛谷——P1809 过河问题_NOI导刊2011提高(01) 题目描述 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸.而东岸边有一条小船. 船太小了,一次只能 ...
- 洛谷 P1808 单词分类_NOI导刊2011提高(01)
P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且仅当 ...
- 洛谷P1808 单词分类_NOI导刊2011提高(01) 字符串排序
洛谷P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且 ...
- P1835 素数密度_NOI导刊2011提高(04)
题目描述 给定区间[L,R](L≤R≤2147483647,R-L≤1000000),请计算区间中素数的个数. 输入输出格式 输入格式: 两个数L和R. 输出格式: 一行,区间中素数的个数. 输入输出 ...
- 单人纸牌_NOI导刊2011提高(04)
单人纸牌 时间限制: 1 Sec 内存限制: 128 MB 题目描述 单人纸牌游戏,共 36 张牌分成 9 叠,每叠 4 张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如 ...
- 素数密度_NOI导刊2011提高(04)
题目描述 给定区间[L, R](L <= R <= 2147483647,R-L <= 1000000),请计算区间中素数的个数. 输入 两个数 L 和 R. 输出 一行,区间中素数 ...
- P1837 单人纸牌_NOI导刊2011提高(04)
题目描述 单人纸牌游戏,共36张牌分成9叠,每叠4张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如黑桃10和梅花10)并且一起拿走.如果最后所有纸牌都被取走,则游戏者就赢了 ...
- 洛谷P1809 过河问题_NOI导刊2011提高(01)
To 洛谷.1809 过河问题 题目描述 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸.而东岸边有一条小船. 船太小了,一次只能乘坐两人.每个人都有一个渡河时 ...
随机推荐
- docker和Dockerfile
目录: 1.docker为什么会出现? 2.docker的理念 3.容器化技术 4.docker三要素 5.docker安装 6.docker帮助命令 7.Docker阿里云镜像加速器配置. 8.do ...
- layer 回调
目前使用的layer版本为1.8.5 在调用layer的JS中,使用end来进行处理 $.layer({ type : 2, shadeClose : true, title : '选择人员', cl ...
- flink⼿手动维护kafka偏移量量
flink对接kafka,官方模式方式是自动维护偏移量 但并没有考虑到flink消费kafka过程中,如果出现进程中断后的事情! 如果此时,进程中段: 1:数据可能丢失 从获取了了数据,但是在执⾏行行 ...
- JavaWeb_(SSH论坛)_四、页面显示
基于SSH框架的小型论坛项目 一.项目入门 传送门 二.框架整合 传送门 三.用户模块 传送门 四.页面显示 传送门 五.帖子模块 传送门 六.点赞模块 传送门 七.辅助模块 传送门 帖子表与回复表 ...
- 分布式-信息方式-ActiveMQ静态网络连接的容错
容错的链接Failover Protocol 前面讲述的都是client配置链接到指定的 broker上.但是,如果 Broker的链接失败怎么办呢?此时, Client有两个选项:要么立刻死掉,要么 ...
- @RequestMapping注解学习
1.@RequestMapping注释用于映射url到控制器类或一个特定的处理程序方法.可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. 参考地址:https://ww ...
- docker-compose部署redis-cluster
node1-node6 1.到http://download.redis.io/redis-stable/redis.conf下载官方redis.conf文件 2.修改对应端口 # bind 127. ...
- .Net 无法打开Offie Open XML文件(上传和下载使用)
代码: 首先,贴一个上传 public static string UploadFileIntoDir(FileUpload MyFile, string DirName) { if (IfOkFil ...
- Node.js读取文件相对路径写法注意
首先看一下文件的存放结构: 我们现在希望在上面标记的JS文件里面读取html里面的内容,我们的代码如下: var fs=require("fs"); fs.readFile('te ...
- save——model模块保存和载入使用简单例子
https://www.w3xue.com/exp/article/201812/10995.html =====1====实践模型存入 import tensorflow as tf from te ...