题面

这道题有点坑人啊~

首先,它需要取模,模数是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. 【杂题】[CodeForces 1172F] Nauuo and Bug【数据结构】【线段树】

    Description 给出一个长度为n的序列a和一个整数p 有m组询问,每组询问给出一个区间\([l,r]\) 你需要给出下面这个过程的结果 ans = 0 for i from l to r { ...

  2. CF contest 1216 Div3. F

    题目链接:Click here Solution: 看起来是贪心,其实不然... 我们定义\(f[i]\)表示仅覆盖\(1\sim i\)所需要的最小代价,那么对\(i\)为0的点来说,易得\(f[i ...

  3. Babel编辑ES6代码

    1.安装babel依赖 npm install --save-dev @babel/core @babel/cli @babel/preset-env npm install --save @babe ...

  4. 五、smarty模板继承特性

    1.如何去实现模板之间的继承 继承是发生在模板之间的事,和PHP程序没有关系的 方法一: 在模板中使用<{extends}>函数实现模板的继承 <{extends file=”模板文 ...

  5. 后盾网lavarel视频项目---3、lavarel中子控制器继承父控制器以判断是否登录

    后盾网lavarel视频项目---3.lavarel中子控制器继承父控制器以判断是否登录 一.总结 一句话总结: 在common控制器的构造方法中验证登录中间件,其它的控制器继承common控制器 p ...

  6. orcal解决锁表

    1.查看历史运行纪录 select * from dba_jobs_running: 2查看锁住的sid和pid select s.sid,s.serial# fromv$session s wher ...

  7. electron创建窗口常用配置参数

    { "width": 800,//指定窗口的宽度,单位: 像素值. 默认是 800 "height":600,//指定窗口的高度,单位: 像素值,. 默认是 6 ...

  8. 浏览器端-W3School-JavaScript:JavaScript Math 对象

    ylbtech-浏览器端-W3School-JavaScript:JavaScript Math 对象 1.返回顶部 1. Math 对象 Math 对象用于执行数学任务. 使用 Math 的属性和方 ...

  9. 《FS Book》: 如何让圣诞节邮件营销与众不同

    临近年末,双旦将至,这无疑是一年中最适合进行营销的时候,各大企业都开始进行促销活动,但与此同时,不要忘了问候你的客户,给他们真切的关怀.国内领先的邮件营销服务商Focussend在其最新一期<F ...

  10. warning: accessed via instance reference

    提示如图: 先简单翻译一下: 静态成员***通过实例对象访问 显示通过类实例而不是类本身调用方法和属性. 现有一个类Test,有静态方法methods和静态属性fields. 对于静态变量或方法,推荐 ...