洛谷 P4112 [HEOI2015]最短不公共子串 解题报告
P4112 [HEOI2015]最短不公共子串
题目描述
在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列
输入输出格式
输入格式:
有两行,每行一个小写字母组成的字符串,分别代表A和B。
输出格式:
输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1
说明
对于20%的数据,A和B的长度都不超过20
对于50%的数据,A和B的长度都不超过500
对于100%的数据,A和B的长度都不超过2000
四合一还行。
问题1
建立B的后缀自动机
枚举A的开头,然后在B上从S向后跑,失配了更新答案
问题2
建立B的序列自动机
然后一样的
问题3
在B的后缀自动机上跑DP(这样才能处理A的子序列)
具体的\(dp_i\)表示这个点可以匹配上的最短长度
从头开始枚举每个点更新。
问题4
在B的序列自动机上跑,其他和三一样
数据太水,3,4的dp01背包写成完全背包也可以过...
我3的dp写的是假的,懒得改了..
Code:
#include <cstdio>
#include <cstring>
const int N=4010;
const int inf=0x3f3f3f3f;
char s1[N],s2[N];
int n,dp[N];
int min(int x,int y){return x<y?x:y;}
struct SuffixAutomata
{
int tot,las,len[N],ch[N][26],par[N];
SuffixAutomata()
{
tot=las=1;
memset(len,0,sizeof(len));
memset(ch,0,sizeof(ch));
memset(par,0,sizeof(par));
}
void extend(int c)
{
int now=++tot,p=las;
len[now]=len[p]+1;
while(p&&!ch[p][c]) ch[p][c]=now,p=par[p];
if(!p) par[now]=1;
else
{
int x=ch[p][c];
if(len[x]==len[p]+1) par[now]=x;
else
{
int y=++tot;
len[y]=len[p]+1,par[y]=par[x];
memcpy(ch[y],ch[x],sizeof ch[y]);
while(p&&ch[p][c]==x) ch[p][c]=y,p=par[p];
par[now]=par[x]=y;
}
}
las=now;
}
void build(char *s)
{
int n=strlen(s+1);
for(int i=1;i<=n;i++) extend(s[i]-'a');
}
}T1;
struct SequentialAutomaton
{
int suc[N],ch[N][26];
SequentialAutomaton()
{
memset(suc,0,sizeof(suc));
memset(ch,0,sizeof(ch));
}
void build(char *s)
{
int n=strlen(s+1);s[0]='a';
for(int i=n;~i;i--)
{
for(int j=0;j<26;j++)
if(suc[j])
ch[i][j]=suc[j];
suc[s[i]-'a']=i;
}
}
}T2;
void work1()
{
int ans=inf;
for(int i=1;i<=n;i++)
{
int now=1;
for(int j=i;j<=n;j++)
{
int c=s1[j]-'a';
if(T1.ch[now][c]) now=T1.ch[now][c];
else
{
ans=min(ans,j+1-i);
break;
}
}
}
if(ans==inf) puts("-1");
else printf("%d\n",ans);
}
void work2()
{
int ans=inf;
for(int i=1;i<=n;i++)
{
int now=0;
for(int j=i;j<=n;j++)
{
int c=s1[j]-'a';
if(T2.ch[now][c]) now=T2.ch[now][c];
else
{
ans=min(ans,j+1-i);
break;
}
}
}
if(ans==inf) puts("-1");
else printf("%d\n",ans);
}
void work3()
{
memset(dp,0x3f,sizeof dp);
dp[1]=0;
int ans=inf;
for(int i=1;i<=n;i++)
{
int c=s1[i]-'a';
for(int j=1;j<=T1.tot;j++)
{
int v=T1.ch[j][c];
if(v) dp[v]=min(dp[v],dp[j]+1);
else ans=min(ans,dp[j]+1);
}
}
if(ans==inf) puts("-1");
else printf("%d\n",ans);
}
void work4()
{
memset(dp,0x3f,sizeof dp);
dp[0]=0;
int ans=inf;
for(int i=1;i<=n;i++)
{
int c=s1[i]-'a';
for(int j=n;~j;j--)
{
int v=T2.ch[j][c];
if(v) dp[v]=min(dp[v],dp[j]+1);
else ans=min(ans,dp[j]+1);
}
}
if(ans==inf) puts("-1");
else printf("%d\n",ans);
}
int main()
{
scanf("%s%s",s1+1,s2+1);
T1.build(s2),T2.build(s2),n=strlen(s1+1);
work1(),work2(),work3(),work4();
return 0;
}
2019.1.7
洛谷 P4112 [HEOI2015]最短不公共子串 解题报告的更多相关文章
- BZOJ 4032 Luogu P4112 [HEOI2015]最短不公共子串 (DP、后缀自动机)
这其实是道水题... 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4032 (luogu)https://www.luog ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- BZOJ 4032: [HEOI2015]最短不公共子串
4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 446 Solved: 224[Submit][Sta ...
- BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力
4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...
- bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...
- luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS
luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...
- bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032:[HEOI2015]最短不公共子串(SAM)
Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...
随机推荐
- Ubuntu学习总结-01 安装Ubuntu
Ubuntu(友帮拓.优般图.乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于Debian GNU/Linux,支持x86.amd64(即x64)和ppc架构,由全球 ...
- 总结 : C#事件理解
要理解事件,首先必须理解委托!! 1.如果说委托是一个类型,那么事件就是一个对象! 2.事件的创建必须是借助某个委托类型来完成的! 3.也就是说,委托是事件的类型,事件本身是个对象!! 4.所以,事件 ...
- 谈谈对Python装饰器的理解
装饰器,又名函数修饰符.笔者觉得函数修饰符,这个名字更能直观的反应他的作用. 函数修饰符语法特征 : @ + 修饰符 函数修饰符的装饰对象: 函数修饰符,就是说他修饰的是 ...
- SQLAlchemy 关联表删除实验
本实验所用代码来源于官网文档 from sqlalchemy import Table, Column, Integer, String, ForeignKey from sqlalchemy.orm ...
- Gitlab+Jenkins学习之路(十四)之自动化脚本部署实践
目录 一.环境说明和准备 1.环境说明 2.服务器准备工作 二.发布脚本编写 1.自动化部署流程设计 2.自动化部署脚本编写 三.发布测试 1.开发机和github添加ssh信任 2.克隆项目到开发机 ...
- dotnet core webapi 发布部署到docker的步骤
1. 创建web api项目,编译并测试成功 2. 在项目的根目录添加Dockerfile文件,注意:Dockerfile文件名区分大小写 文件内容如下 # 基于microsoft/dotnet:la ...
- 如何控制iOS的导航栏和状态栏的样式
这是一个很常用的开发场景,就是改变导航栏上的文字颜色与背景色,如果你曾有 windows form 开发经验一定会笑我:"卧槽,这有什么好写的,不就是设置两个属性就可以了吗?" 我 ...
- Json和Map互转,四个包(org.json/net.sf.json/com.google.gson/com.alibaba.fastjson)
目前使用的(org.json/net.sf.json/com.google.gson/com.alibaba.fastjson)这四种json-map互转,其他的以后在补充.............. ...
- Azkaban集群部署
一.部署模式 solo-server模式 (使用内置h2存储元数据): two-server模式 (1个webServer,1个execServer在同一服务器上,使用mysql存储元数据): mu ...
- Google Kickstart Round.B C. Diverse Subarray
这题又是万恶的线段树 maxx[j]存储的是 l = xxx, r = j的时候的答案 我们会让 l 从 1到n 的遍历中,查询线段树的[l, n]中最大的答案 因为query的下界是n,所以单次查询 ...