bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串
题目:传送门
题解:
陈年老题良心%你赛膜爆嘎爷
当初做题...一眼SAM...结果只会两种直接DP的情况...
情况1: 直接设f[i][j] 表示的是a串的第i个位置和b串的第j个位置开始的最长公共前缀(灵感来源于SA)。然后就枚举开头直接瞎搞啊。。。
情况2: 定义一个last[i][j] 表示b串的位置i后面的第一个字符j,贪心的思想直接做,匹配不到位置就直接记录答案了嘛
情况3: 因为是在b串当中找子串,a中找子序列,那就考虑对b建SAM,然后定义da[] 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度(具体看代码)、
情况4: 利用情况2预处理的last,贪心思想,仿照情况三把last当作自动机来跑
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define inf 1e9
using namespace std;
struct SAM
{
int son[];
}ch[];int cnt,dep[],a[],fail[],da[],la,root,ss;、
//da 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度
void add(int k)
{
int x=a[k];
int p=la,np=++cnt;dep[np]=k;
while(p!= && ch[p].son[x]==)ch[p].son[x]=np,p=fail[p];
if(p==)fail[np]=root;
else
{
int q=ch[p].son[x];
if(dep[p]+==dep[q])fail[np]=q;
else
{
int nq=++cnt;dep[nq]=dep[p]+;
ch[nq]=ch[q];fail[nq]=fail[q];fail[np]=fail[q]=nq;
while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=fail[p];
}
}
la=np;
}
int len1,len2,opt;
int c[],last[][];//位置i后面的第一个字符j
char sa[],sb[];
int f[][];//分别以i,j位置开头的最长公共前缀
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
//scanf("%d",&opt);
scanf("%s",sa+);len1=strlen(sa+);
scanf("%s",sb+);len2=strlen(sb+);
//if(opt==1)
//{
memset(f,,sizeof(f));int ans=inf,len=,maxx=;
for(int i=len1;i>=;i--)for(int j=len2;j>=;j--)if(sa[i]==sb[j])f[i][j]=f[i+][j+]+;
for(int i=;i<=len1;i++)
{
maxx=;for(int j=;j<=len2;j++)maxx=max(maxx,f[i][j]);
if(maxx!=len1-i+)ans=min(ans,maxx+);//加一定不相等
}
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
//}
//else if(opt==2)
//{
len=,ans=inf;for(int i=;i<=;i++)c[i]=inf;sb[]='a';
for(int i=len2;i>=;i--){for(int j=;j<=;j++)last[i][j]=c[j];c[sb[i]-'a'+]=i;}
for(int i=;i<=len1;i++)
{
len=;
for(int j=i;j<=len1;j++)
{
len=last[len][sa[j]-'a'+];
if(len>len1){ans=min(ans,j-i+);break;}//跳出去证明没有了
}
}
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
//}
// else if(opt==3)
// {
cnt=;root=la=++cnt;memset(da,,sizeof(da));
for(int i=;i<=len2;i++)a[i]=sb[i]-'a';for(int i=;i<=len2;i++)add(i);ss=;da[]=;ans=inf;
for(int i=;i<=len1;i++)
for(int j=;j<=cnt;j++)
{
ss=ch[j].son[sa[i]-'a'];
if(ss==)ans=min(ans,da[j]+);else da[ss]=min(da[ss],da[j]+);
}
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
// }
//else if(opt==4)
//{
ans=inf;//for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a';
//for(int i=len2;i>=0;i--){for(int j=1;j<=26;j++)last[i][j]=c[j];c[sb[i]-'a'+1]=i;}
memset(da,,sizeof(da));da[]=;ss=;
for(int i=;i<=len1;i++)
for(int j=len2;j>=;j--)
{
ss=last[j][sa[i]-'a'+];
if(ss>len1)ans=min(ans,da[j]+);else da[ss]=min(da[ss],da[j]+);
}
if(ans==inf)printf("-1\n");
else printf("%d\n",ans);
//}
return ;
}
bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)的更多相关文章
- [BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)
在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之——被它们虐. 操作一:对A,B分别建SAM,暴力BFS. 操作二:对B建序列自动机或SAM,A在上面暴力匹配. 操作三:对A,B建 ...
- BZOJ4032:[HEOI2015]最短不公共子串(SAM)
Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...
- luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS
luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】
题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...
- bzoj 4032: [HEOI2015]最短不公共子串【dp+SAM】
第一.二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i-1][j-1]+1:0),第二问的转移是f[i][j] ...
- BZOJ4032 : [HEOI2015]最短不公共子串
第一问: 对B串建立SAM,暴力枚举A的每个子串,在SAM上走,若失配则可行. 第二问: 设g[i][j]表示B串的第i个字符之后最早出现的字符j的位置,暴力枚举A的每个子串,按照g贪心地走,若失配则 ...
- bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...
随机推荐
- BZOJ 4403 2982 Lucas定理模板
思路: Lucas定理的模板题.. 4403 //By SiriusRen #include <cstdio> using namespace std; ; #define int lon ...
- POJ 2299 求逆序对个数 归并排序 Or数据结构
题意: 求逆序对个数 没有重复数字 线段树实现: 离散化. 单点修改,区间求和 // by SiriusRen #include <cstdio> #include <cstring ...
- 代理模式(Proxy)C++实现
代理模式 尽管Decorator的实现部分与代理相似,但Decorator的目的不一样.Decorator为对象添加一个或多个功能,而代理则控制对对象的访问. 意图: 为其他对象提供一种代理以控制对这 ...
- java RPC系列之二 HTTPINVOKER
java RPC系列之二 HTTPINVOKER 一.java RPC简单的汇总 java的RPC得到技术,基本包含以下几个,分别是:RMI(远程方法调用) .Caucho的Hessian 和 Bu ...
- mac 下安装 mariadb
通过brew 安装: brew install mariadb 初始化数据库 cd /usr/local/Cellar/mariadb/10.0.10/scripts mysql_install_db ...
- RabbitMQ学习之集群模式
由于RabbitMQ是用erlang开发的,RabbitMQ完全依赖Erlang的Cluster,因为erlang天生就是一门分布式语言,集群非常方便,但其本身并不支持负载均衡.Erlang的集群中各 ...
- C#的split函数分割
C#的split函数分割 string str = textBox1.Text; string[] strlist = str.Split("\r\n".ToCharArray() ...
- 应用一:Vue之开发环境搭建
简单分享下vue项目的开发环境搭建流程~ 1.安装nodeJS vue的运行是要依赖于node的npm的管理工具来实现,下载地址:https://nodejs.org/en/.安装完成之后以管理员身份 ...
- Linux 命令查询系统负载信息
linux uptime命令主要用于获取主机运行时间和查询linux系统负载等信息.uptime命令过去只显示系统运行多久.现在,可以显示系统已经运行了多长 时间,信息显示依次为:现在时间.系统已经运 ...
- vue 绑定 HTML Class
绑定 HTML Class