序列自动机:

是一个处理子序列的自动机。就这样。

建造:(By猫老师:immoralCO猫)

s[]
next[][]
memset(next[n], -, <<);
for(int i = n; i; --i) {
memcpy(next[i - ], next[i], << );
next[i - ][s[i] - 'a'] = i;
}

nxt[][]数组就是第几个位置,序号为几的出边连接到第几个位置(位置是对应字符串的位置,其实并没用)

大概原理就是每当要循环到字符串中的一个位置,就把这个位置的连通性赋值给上一个节点编号,(可以理解,n个字符,其实是n条边,最多有n+1个节点在两边)

然后处理新来的字符i对于i-1号位置连通性的影响,那么,

编号从0~n,其中0号点就是根,dfs从0开始。

(不会的话,手动模拟就好了)

发现,当子序列中有重复元素的时候,nxt[i-1][s[i]-'a']=i一句可以将这种情况覆盖掉。

由于这些0~n号节点可以重复到达,当然最终到了n号点就是边界了。

所以dfs没有问题。而且大大节省了空间。

这样,我们可以只用有限的O(长度*|S|)的空间,来建造这棵树。

发现,这棵树好像trie啊~!!!!

其实差不多,一个子序列,一个子串。

操作也就和trie差不多了。

基本操作:

1.可以统计一个串本质不同的子序列的个数

序列自动机上可以是一棵树,树上每一个节点到根的路径上的边所代表的字符串就是所有的本质不同的子序列。

dfs树上扫一遍就好了。

2.可以查找一个子序列是否在这个字符串中出现过。

显然,dfs就可以。

3.也可以两个序列自动机一起dfs,找到所有公共子序列。

就比如说这个题:

(真是序列自动机板子题)

[FJOI2016]所有公共子序列问题

题目大意:给定两个字符串,求这两个串的所有公共子序列。

当输入的参量k=1的时候,按照字典序输出这些子序列,并输出个数。

当输入的参量k=0的时候,输出个数就可以。

注意,空字符串也是一个公共子序列。

分析:

裸裸裸裸的序列自动机。

开两个自动机,直接同时跑dfs就可以。

对于k=1,就要先走a,再走z,条件是两个都可以走,一遍用一个栈一样的字符串记录字符串。进入循环就输出即可。并且记录总数。

对于k=0,同理。

诶,怎么我的long long出了负数呢??

因为要高精。

诶,怎么我的高精MLE了呢????

因为要压位高精。

https://www.cnblogs.com/Miracevin/p/9031691.html

但是这个版本太弱了,很久以前写的。

所以,用结构体实现就比较方便了。结构体内置函数。

支持:高精加低精(因为要赋初值1(其实直接赋值也可以)),高精加高精,压位高精的输出。

没了。

看代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9;
const int N=;
const int L=;
const int K=;
int nxt1[N][L],nxt2[N][L];
char sta[N];
int top=-;
ll ans;
int la,lb,k;
char a[N],b[N];
struct Big{//压位结构体
int cur;
ll *s;
void init(){
s=new long long[];
for(int i=;i<;i++) s[i]=;
cur=;
}
void put(){
printf("%lld",s[cur]);
for(int i=cur-;i>=;i--) printf("%09lld",s[i]);
}
void add(ll k){
s[]+=k;
int i=;
while(s[i]>=mod) s[i+]+=s[i]/mod,s[i++]%=mod;
while(s[cur+]) cur++;
}
void Add(const Big& o){
ll i,r=max(cur,o.cur);
for(int i=;i<=r;i++){
s[i]+=o.s[i];
if(s[i]>=mod) s[i+]+=s[i]/mod,s[i]%=mod;
}
cur=min(r+,19ll);while(cur&&s[cur]==) cur--;
}
}dp[N][N];
bool vis[N][N];
void build1(){//建造序列自动机
memset(nxt1[la],-,sizeof nxt1[la]);
for(int i=la;i;i--){
memcpy(nxt1[i-],nxt1[i],sizeof nxt1[i]);
nxt1[i-][a[i]-'A']=i;
}
}
void build2(){
memset(nxt2[lb],-,sizeof nxt2[lb]);
for(int i=lb;i;i--){
memcpy(nxt2[i-],nxt2[i],sizeof nxt2[i]);
nxt2[i-][b[i]-'A']=i;
}
}
void dfs2(int x,int y){//dfs
if(vis[x][y]) return;
vis[x][y]=;
dp[x][y].init();
dp[x][y].add();
for(int i=;i<=;i++){
if(nxt1[x][i]!=-&&nxt2[y][i]!=-) {
dfs2(nxt1[x][i],nxt2[y][i]);
dp[x][y].Add(dp[nxt1[x][i]][nxt2[y][i]]);
}
}
}
ll dfs1(int x,int y){
printf("%s\n",sta);
ll cnt=;
for(int i=;i<=;i++){
if(nxt1[x][i]!=-&&nxt2[y][i]!=-) {
sta[++top]=i+'A';
cnt+=dfs1(nxt1[x][i],nxt2[y][i]);
sta[top--]=' ';
}
}
return cnt;
}
int main()
{
scanf("%d%d",&la,&lb);
scanf("%s",a+);scanf("%s",b+);
scanf("%d",&k);
build1();build2();
if(k==) {
dfs1(,);
}
dfs2(,);
dp[][].put();
return ;
}

序列自动机—— [FJOI2016]所有公共子序列问题的更多相关文章

  1. hunnu 11313 无重复元素序列的最长公共子序列转化成最长递增子序列 求法及证明

    题目:http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11313 湖师大的比赛,见我的另一篇水题题解,这里要说的 ...

  2. 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】

    题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...

  3. [csu/coj 1078]多个序列的最长公共子序列

    题意:给n个序列,同一个序列里面元素互不相同,求它们的最长公共子序列. 思路:任取一个序列,对于这个序列里面的两个数ai,aj(i<j),如果对于其它每一个序列,都出现过ai,aj,且ai在aj ...

  4. luogu4608 [FJOI2016]所有公共子序列问题

    题目描述: luogu loj 题解: 序列自动机(?)+高精+普及dp. 这个是猫老师的序列自动机(字符串从1开始): ]) { memset(t[n],-,sizeof(t[n])); ;i> ...

  5. 【LCS,LIS】最长公共子序列、单调递增最长子序列

    单调递增最长子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4   输入 ...

  6. 后缀自动机&序列自动机综合

    好像序列自动机还没有写过- 串长为n的串共有n+1个节点,除了串中的n个节点,还有一个空的根节点放在串首.每个节点至多有26条出边,每条边连向它之后的第一个字符. 串中的任意一个子序列对应了一条根到某 ...

  7. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  8. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  9. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

随机推荐

  1. Nginx基于TCP/UDP端口的四层负载均衡(stream模块)配置梳理

    通过我们会用Nginx的upstream做基于http/https端口的7层负载均衡,由于Nginx老版本不支持tcp协议,所以基于tcp/udp端口的四层负载均衡一般用LVS或Haproxy来做.至 ...

  2. 在Mac终端显示 Git 当前所在分支

    1.进入你的home目录 cd ~ 2.编辑.bashrc文件 vi .bashrc 3.将下面的代码加入到文件的最后处 function git_branch { branch="`git ...

  3. 作业20171130 final发布 成绩

    申诉 对成绩有疑问或不同意见的同学,请在群里[@杨贵福]. 申诉时间截止2017年12月16日 17:00. 更新 第一周和第二周成绩分别应占比20%和10%,计算时刚好反了.所以同学们的最终成绩有变 ...

  4. M2阶段团队个人贡献分

    团队个人贡献分: 徐钧鸿:53 张艺:48 黄可嵩:51 徐方宇:47 刘浩然:52 钟毅恒:49 杨伊:50

  5. 2-Twenty Fifth Scrum Meeting-20151231

    前言 因为服务器关闭,我们的开发项目也遭遇停滞一个星期.与网站开发负责人员协商之后,29号开放服务器.我们的项目也能够继续下去.比规定的开发时间(截止为2015/12/29)推迟. 事项安排 1.开发 ...

  6. sqlalchemy 使用pymysql连接mysql 1366错误

    一.错误情况 mysql 5.7.2 \python35\lib\site-packages\pymysql\cursors.py:166: Warning: (1366, "Incorre ...

  7. netsh 转发 5000 端口到 80端口的命令和删除方法

    归集整理一下 netsh 的几个简单命令. 实现端口转发等作用. 注意 命令. netsh connectaddress= listenaddress 的地址 目的 是 对外服务的 target 的 ...

  8. SQLSERVER安装

    sql server 2008 代理服务提供的凭据无效 sql server 2008 代理服务提供的凭据无效 在Windows Server 2008安装SQL Server 2008出现的问题: ...

  9. 一步步分析为什么B+树适合作为索引的结构

    在MySQL中,主要有四种类型的索引,分别为:B-Tree索引,Hash索引,Fulltext索引和R-Tree索引,本文讲的是B-Tree索引. 什么是索引 索引(Index)是帮助数据库高效获取数 ...

  10. Bootstrap图像

    前面的话 图像在网页制作中也是常要用到的元素,本文将详细介绍Bootstrap图像 响应式图片 通过为图片添加 .img-responsive 类可以让图片支持响应式布局.其实质是为图片设置了 max ...