题面

这道题有点坑人啊~

首先,它需要取模,模数是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)题的更多相关文章

  1. P1836 【数页码_NOI导刊2011提高(04)】

    P1836 数页码_NOI导刊2011提高(04) 题目描述 一本书的页码是从1—n编号的连续整数:1,2,3,…,n.请你求出全部页码中所有单个数字的和,例如第123页,它的和就是1+2+3=6. ...

  2. 贪心—— P1809 过河问题_NOI导刊2011提高(01)

    洛谷——P1809 过河问题_NOI导刊2011提高(01) 题目描述 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸.而东岸边有一条小船. 船太小了,一次只能 ...

  3. 洛谷 P1808 单词分类_NOI导刊2011提高(01)

    P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且仅当 ...

  4. 洛谷P1808 单词分类_NOI导刊2011提高(01) 字符串排序

    洛谷P1808 单词分类_NOI导刊2011提高(01) 题目描述 Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类. 两个单词可以分为一类当且 ...

  5. P1835 素数密度_NOI导刊2011提高(04)

    题目描述 给定区间[L,R](L≤R≤2147483647,R-L≤1000000),请计算区间中素数的个数. 输入输出格式 输入格式: 两个数L和R. 输出格式: 一行,区间中素数的个数. 输入输出 ...

  6. 单人纸牌_NOI导刊2011提高(04)

    单人纸牌 时间限制: 1 Sec  内存限制: 128 MB 题目描述 单人纸牌游戏,共 36 张牌分成 9 叠,每叠 4 张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如 ...

  7. 素数密度_NOI导刊2011提高(04)

    题目描述 给定区间[L, R](L <= R <= 2147483647,R-L <= 1000000),请计算区间中素数的个数. 输入 两个数 L 和 R. 输出 一行,区间中素数 ...

  8. P1837 单人纸牌_NOI导刊2011提高(04)

    题目描述 单人纸牌游戏,共36张牌分成9叠,每叠4张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如黑桃10和梅花10)并且一起拿走.如果最后所有纸牌都被取走,则游戏者就赢了 ...

  9. 洛谷P1809 过河问题_NOI导刊2011提高(01)

    To 洛谷.1809 过河问题 题目描述 有一个大晴天,Oliver与同学们一共N人出游,他们走到一条河的东岸边,想要过河到西岸.而东岸边有一条小船. 船太小了,一次只能乘坐两人.每个人都有一个渡河时 ...

随机推荐

  1. jquery input选择器 语法

    jquery input选择器 语法 作用::input 选择器选取表单元素.该选择器同样适用于 <button> 元素.大理石平台价格表 语法:$(":input") ...

  2. linux中的selinux到底是什么

    一文彻底明白linux中的selinux到底是什么 2018年06月29日 14:17:30 yanjun821126 阅读数 58877 标签: SElinux 更多 个人分类: Linux   一 ...

  3. hdu 3572 仪器与任务 最大流 好题 体会建图思想

    Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  4. 洛谷P1576 最小花费x

    题目背景 题目描述 在n个人中,某些人的银行账号之间可以互相转账.这些人之间转账的手续费各不相同.给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元 ...

  5. Haystack全文检索框架

    一.什么是Haystack Haystack是django的开源全文搜索框架(全文检索不同于特定字段的模糊查询,使用全文检索的效率更高 ),该框架支持Solr,Elasticsearch,Whoosh ...

  6. SQL中模糊查询的模式匹配

    SQL模糊查询的语法为: “Select column FROM table Where column LIKE 'pattern'”. SQL提供了四种匹配模式: 1. % 表示任意0个或多个字符. ...

  7. git 更改远程仓库地址,强行推送远程仓库

    强行推送远程仓库 #把一个现有的工程拷贝一份 #去掉远程仓库关联 git remote rm origin #添加远程仓库关联 git remote add origin http://xxx.git ...

  8. 云服务器搭建anaconda pytorch torchvision

    (因为在普通用户上安装有些权限问题安装出错,所以我在root用户下相对容易安装,但是anaconda官网说可以直接在普通用户下安装,不过,在root下安装,其他用户也是能用的. 访问Anaconda官 ...

  9. 一、Smarty安装与调试

    一.安装注:这里所使用的Smarty是3.x版本,要求PHP版本为5.2或者更高.解压下载下来的Smarty压缩文件,将文件夹libs拷到项目中,在项目中引入libs文件夹中的"Smarty ...

  10. MyExcel 2.2.0 版本发布,支持公式导出

    MyExcel,是一个集导入.导出.加密Excel等多项功能的java工具包. 相关链接 MyExcel 的详细介绍:点击查看 MyExcel 的下载地址:点击下载