BZOJ4032:[HEOI2015]最短不公共子串(SAM)
Description
在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
Input
有两行,每行一个小写字母组成的字符串,分别代表A和B。
Output
输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.
Sample Input
abcabc
Sample Output
4
2
4
HINT
对于100%的数据,A和B的长度都不超过2000
Solution
强行四合一?
(一)枚举$A$串的左端点,然后从左端点开始往后在$B$串的$SAM$上面跑,一旦失配就更新答案然后$break$
(二)预处理数组$next[i][j]$表示从$i$后面的第一次出现字母$j$的位置。预处理出$nextA$和$nextB$,然后枚举$A$左端点往后贪心,如果失配就更新答案然后$break$
(三)设$len[i]$表示在$B$串的$SAM$的$i$点的时候最短的长度。然后用$A$串在$B$的$SAM$上面跑。如果失配就更新答案,否则就更新$len$。
(四)设$len[i]$表示在$B$串的$i$位置的时候最短的长度。然后用$A$串的每一个字母,借$next$数组倒序去更新$len$。如果失配就更新答案,否则就更新$len$。至于为什么要倒序,其实是和背包差不多的原理,并不难想。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (4009)
using namespace std; char s[N],t[N];
int slen,tlen,nextA[N][],nextB[N][],last[],len[N]; struct SAM
{
int son[N][],fa[N],step[N],wt[N],od[N];
int p,q,np,nq,last,cnt;
SAM(){last=cnt=;} void Insert(int x)
{
p=last; np=last=++cnt; step[np]=step[p]+;
while (p && !son[p][x]) son[p][x]=np, p=fa[p];
if (!p) fa[np]=;
else
{
q=son[p][x];
if (step[q]==step[p+]) fa[np]=q;
else
{
nq=++cnt; step[nq]=step[p]+;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q]; fa[np]=fa[q]=nq;
while (son[p][x]==q) son[p][x]=nq, p=fa[p];
}
}
}
}SAM; void CalcNext()
{
memset(last,-,sizeof(last));
for (int i=slen; i>=; --i)
{
for (int j=; j<; ++j) nextA[i][j]=last[j];
last[s[i]-'a']=i;
}
memset(last,-,sizeof(last));
for (int i=tlen; i>=; --i)
{
for (int j=; j<; ++j) nextB[i][j]=last[j];
last[t[i]-'a']=i;
}
} void Sub1()
{
int ans=2e9;
for (int i=; i<=slen; ++i)
{
int now=;
for (int j=i; j<=slen; ++j)
{
if (!SAM.son[now][s[j]-'a']) {ans=min(ans,j-i+); break;}
now=SAM.son[now][s[j]-'a'];
}
}
printf("%d\n",ans==2e9?-:ans);
} void Sub2()
{
int ans=2e9;
for (int i=; i<=slen; ++i)
{
int now=;
for (int j=i; j<=slen; ++j)
{
if (nextB[now][s[j]-'a']==-) {ans=min(ans,j-i+); break;}
now=nextB[now][s[j]-'a'];
}
}
printf("%d\n",ans==2e9?-:ans);
} void Sub3()
{
int ans=2e9;
memset(len,0x7f,sizeof(len));
len[]=;
for (int i=; i<=slen; ++i)
for (int j=; j<=SAM.cnt; ++j)
{
int nxt=SAM.son[j][s[i]-'a'];
if (!nxt) ans=min(ans,len[j]);
else len[nxt]=min(len[nxt],len[j]+);
}
printf("%d\n",ans==2e9?-:ans);
} void Sub4()
{
int ans=2e9;
memset(len,0x7f,sizeof(len));
len[]=;
for (int i=; i<=slen; ++i)
for (int j=tlen; j>=; --j)
{
int nxt=nextB[j][s[i]-'a'];
if (nxt==-) ans=min(ans,len[j]+);
else len[nxt]=min(len[nxt],len[j]+);
}
printf("%d\n",ans==2e9?-:ans);
} int main()
{
scanf("%s%s",s+,t+);
slen=strlen(s+), tlen=strlen(t+);
for (int i=; i<=tlen; ++i)
SAM.Insert(t[i]-'a');
CalcNext();
Sub1(); Sub2(); Sub3(); Sub4();
}
BZOJ4032:[HEOI2015]最短不公共子串(SAM)的更多相关文章
- bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...
- luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS
luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...
- [BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)
在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之——被它们虐. 操作一:对A,B分别建SAM,暴力BFS. 操作二:对B建序列自动机或SAM,A在上面暴力匹配. 操作三:对A,B建 ...
- BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】
题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...
- BZOJ4032 : [HEOI2015]最短不公共子串
第一问: 对B串建立SAM,暴力枚举A的每个子串,在SAM上走,若失配则可行. 第二问: 设g[i][j]表示B串的第i个字符之后最早出现的字符j的位置,暴力枚举A的每个子串,按照g贪心地走,若失配则 ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...
随机推荐
- openvpn应用场景案例【转】
转载至:http://www.linuxfly.org/post/86/ 一.案例1 针对不同的客户端指定不同的等级和权限.通常的方法是:1.每个客户端分配不同的IP地址:2.利用防火墙对不同的IP地 ...
- C#PrintDocument打印尺寸调整
/// <summary> /// 打印的按钮 /// </summary> /// <param name="sender"></par ...
- 完美世界-Java游戏开发-二面
时间:2017-03-30 时长:15分 类型:二面 面试官比较聊得来,人比较和善,游戏面试还是nice的,老铁 1. 自我介绍 2. 平时玩哪些游戏?端游.页游 3. Maven你是怎么使用的? 4 ...
- Django(二):url和views
网络通讯的本质是socket,从socket封装到MVC模式,参见另外几篇博客.本节笔记整理自Django2.0官方文档. 一.url调度器 - django.urls.path django2.0中 ...
- ubuntu关机重启命令
重启命令 : 1.reboot 2.shutdown -r now 立刻重启 3.shutdown -r 10 过10分钟自动重启 4.shutdown -r 20:35 ...
- 【SSH网上商城项目实战08】查询和删除商品类别功能的实现
转自:https://blog.csdn.net/eson_15/article/details/51338991 上一节我们完成了使用DataGrid显示所有商品信息,这节我们开始添加几个功能:添加 ...
- 0 test classes found in package in XXXX
除了参考其他的方法,要注意XXXX位置下是否有空文件夹,删掉.
- POJ P2318 TOYS与POJ P1269 Intersecting Lines——计算几何入门题两道
rt,计算几何入门: TOYS Calculate the number of toys that land in each bin of a partitioned toy box. Mom and ...
- 常用SEO优化
- Web开发须知的浏览器内幕 缓存与存储篇(2)
本文禁止转载,由UC浏览器内部出品. 3. HTTP Cache 综述 HTTP Cache是完全按照IETF规范实现的,最新的RFC规范地址是 https://tools.ietf.org/html ...