题面

这道题有点坑人啊~

首先,它需要取模,模数是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. Spring后台,通过name取值

    表单中,有同名控件(text/hidden/checkbox.......)的情况下,采用getParameterValues("name"):String[] 表单中,只有一个n ...

  2. stat:查看文件时间参数

    Linux 系统中,每个文件主要拥有 3 个时间参数,分别是文件的访问时间.数据修改时间以及状态修改时间: 访问时间(Access Time,简称 atime):只要文件的内容被读取,访问时间就会更新 ...

  3. Python惯例

    “惯例”这个词指的是“习惯的做法,常规的办法,一贯的做法”,与这个词对应的英文单词叫“idiom”.由于Python跟其他很多编程语言在语法和使用上还是有比较显著的差别,因此作为一个Python开发者 ...

  4. win7系统安装Mysql5.7

    1.下载mysql的zip包 把zip包解压到指定的目录,目录不能有中文和空格 2.进入%mysql%目录(注:%mysql%是解压目录,我的是:D:\JavaTool\mysql) 在%mysql% ...

  5. spring整合之后运行报什么只读错误。Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

    解决办法, 再大dao的实现类上添加注解: @Transactional(readOnly = false ) 不让它只读就行了

  6. pom.xml报Plugin execution not covered by lifecycle configuration错误

    环境     eclipse 4.3.0     maven 3.0.4     m2e 1.4.0      出现场景     以前的老项目,在我的环境(我的环境较新)下,别人老环境不报错. 错误示 ...

  7. Activity 怎么和 Service 绑定,怎么在 Activity 中启动自己对应的 Service?

    Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 进行绑定,当绑定成功的时候 Se ...

  8. Windows 10 无法访问共享的解决办法大全

    本文前面介绍 Windows 10 操作系统无法访问其他电脑的共享文件夹,而其他电脑访问该共享可以访问的解决办法. 简单点说就是,你的操作系统是 Win10 ,你访问不了某台电脑的共享,但是别人可以. ...

  9. Python学习之==>条件判断

    1.单条件判断 # 接收输入的值,使用input函数,用input接收输入的值都是string类型的 age = input('请输入你的年龄:') age = int(age) # 类型转换,转换成 ...

  10. Python 解决八皇后问题

    问题介绍 八皇后问题是一个以国际象棋为背景的问题:如何能够在 \(8\times8\) 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一 ...