bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
题解时间
给两个小写字母串 $ A $ , $ B $ ,请你计算:
(1) $ A $ 的一个最短的子串,它不是 $ B $ 的子串
(2) $ A $ 的一个最短的子串,它不是 $ B $ 的子序列
(3) $ A $ 的一个最短的子序列,它不是 $ B $ 的子串
(4) $ A $ 的一个最短的子序列,它不是 $ B $ 的子序列
水题四合一,一题更比四题sao
首先由于都是要从 $ A $ 中找,所以按照套路是把 $ A $ 在 $ B $ 上匹配
所以先构建出 $ B $ 的SAM和序列自动机。
序列自动机:就是一个 $ next[i][ch] $ 数组表示第 $ i $ 位往后第一个出现字符 $ ch $ 的位置,纯粹用来匹配的。
(1) 直接以 $ A $ 每一位为起点在 $ B $ 的SAM上暴力匹配,只要失配就更新答案然后跳出。
(2) 换成在序列自动机上。
(3) $ dp[i][j] $ 表示 $ A $ 的前 $ i $ 个字符形成的子序列在 $ B $ 的SAM上匹配到了 $ j $ 位置,此时形成的最短子序列长度,这是个挺经典的dp了。
(4) 换成在序列自动机上。
#include<bits/stdc++.h>
using namespace std;
namespace RKK
{
const int N=2011,inf=0x3f3f3f3f;
int n1;char s1[N];
int n2;char s2[N];
struct remilia{int tranc[26],len,pre;};
struct sakuya
{
remilia s[N<<1];
int fin,size;
sakuya(){fin=size=1;}
void ins(int ch)
{
int npx,npy,lpx,lpy;
npx=++size;
s[npx].len=s[fin].len+1;
for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
if(!lpx) s[npx].pre=1;
else
{
lpy=s[lpx].tranc[ch];
if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
else
{
npy=++size;
s[npy]=s[lpy];
s[npy].len=s[lpx].len+1;
s[lpy].pre=s[npx].pre=npy;
while(s[lpx].tranc[ch]==lpy)
{
s[lpx].tranc[ch]=npy;
lpx=s[lpx].pre;
}
}
}
fin=npx;
}
void insert(char *str,int sl)
{
for(int i=1;i<=sl;i++)
ins(str[i]-'a');
}
}sam;
struct flandre
{
int ne[N][26],tmp[26];
void insert(char *s,int sl)
{
for(int i=sl;i>=0;i--)
memcpy(ne[i],tmp,104),tmp[s[i]-'a']=i;
}
}sem;
void solve1()
{
int ans=inf;
for(int sp=1;sp<=n1;sp++)
{
int px=1;
for(int i=sp;i<=n1;i++)
{
if(!sam.s[px].tranc[s1[i]-'a']){ans=min(ans,i-sp+1);break;}
px=sam.s[px].tranc[s1[i]-'a'];
}
}
printf("%d\n",ans==inf?-1:ans);
}
void solve2()
{
int ans=inf;
for(int sp=1;sp<=n1;sp++)
{
int px=0;
for(int i=sp;i<=n1;i++)
{
if(!sem.ne[px][s1[i]-'a']){ans=min(ans,i-sp+1);break;}
px=sem.ne[px][s1[i]-'a'];
}
}
printf("%d\n",ans==inf?-1:ans);
}
int dp[N<<1];
void solve3()
{
int ans=inf;
memset(dp,0x3f,sizeof(dp));
dp[1]=0;
for(int i=1;i<=n1;i++)
{
for(int x=sam.size;x;x--)
{
if(sam.s[x].tranc[s1[i]-'a']) dp[sam.s[x].tranc[s1[i]-'a']]=min(dp[sam.s[x].tranc[s1[i]-'a']],dp[x]+1);
else ans=min(ans,dp[x]+1);
}
}
printf("%d\n",ans==inf?-1:ans);
}
void solve4()
{
int ans=inf;
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for(int i=1;i<=n1;i++)
{
for(int x=n2;x>=0;x--)
{
if(!sem.ne[x][s1[i]-'a']) ans=min(ans,dp[x]+1);
else dp[sem.ne[x][s1[i]-'a']]=min(dp[sem.ne[x][s1[i]-'a']],dp[x]+1);
}
}
printf("%d\n",ans==inf?-1:ans);
}
int Iris()
{
scanf("%s%s",s1+1,s2+1),n1=strlen(s1+1),n2=strlen(s2+1);
sam.insert(s2,n2),sem.insert(s2,n2);
solve1(),solve2(),solve3(),solve4();
return 0;
}
}
int main(){return RKK::Iris();}
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)的更多相关文章
- BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力
4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...
- bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...
- BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)
传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...
- bzoj 4032 [ HEOI 2015 ] 最短不公共子串 —— 后缀自动机+序列自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 序列自动机其实就是每个位置记录一下某字母后面第一个出现位置,为了子序列能尽量长. 对字 ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS
luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...
- bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...
- 洛谷 P4112 [HEOI2015]最短不公共子串 解题报告
P4112 [HEOI2015]最短不公共子串 题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的"子串"指的是它的连续的一段,例如bcd是 ...
- BZOJ 4032: [HEOI2015]最短不公共子串
4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 446 Solved: 224[Submit][Sta ...
随机推荐
- Solution -「UR #21」「UOJ #632」挑战最大团
\(\mathcal{Description}\) Link. 对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...
- Solution -「POJ 3710」Christmas Game
\(\mathcal{Decription}\) Link. 定义一棵圣诞树: 是仙人掌. 不存在两个同一环上的点,度数均 \(\ge 3\). 给出 \(n\) 棵互不相关的圣诞树,双人 ...
- Linux命令行模式下安装VMware Tools详细步骤
在Linux命令行模式安装VMware Tools 方法/步骤1: 首先启动CentOS 7,在VMware中点击上方"VM",点击"Install VMware Too ...
- NSSCTF-finalrce
菜狗的我打开题目之后,人都给我吓傻了,直接过滤的超出了我的认知 菜狗直接就枯了,这个题目其实是不难的,就是比较阴间的一个题目,审计代码,可以看到最后一行的代码"exec($url)&quo ...
- [数据生成器]UVA10054 The Necklace
应吴老师之邀,写了个数据生成器. 目前这个数据生成器可以保证生成的数据都是合法的,且效率也还不错.只是在建立普通连通图的时候zyy偷懒了,直接把所有点串起来从而保证图的连通.如果有大神有更好的方法请不 ...
- 大数据BI系统挖掘企业业务上的价值
相信关注过我们的肯定知道BI是什么,但是老话常谈以防新朋友不知道BI的含义,BI(Business Intelligence)即商务智能,它是一套完整的解决方案,用来将企业中现有的数据进行有效的整合 ...
- Python "爬虫"出发前的装备之二数据先行( Requests 模块)
1. 概念 爬虫不是动物,而是一种计算机程序. 这种程序有自己特定的功能,能按照使用者给定的一系列规则自行浏览万维网并获取需要的信息.此类程序被称为 网络爬虫(web crawler) 或 网络蜘蛛( ...
- IDisposable?释放非托管资源接口
原文:https://www.cnblogs.com/luminji/archive/2011/03/29/1997812.html IDisposable高级篇:https://docs.micro ...
- Codeforces Round #750 (Div. 2) E. Pchelyonok and Segments
传送门 题目大意: 给一个序列,可以在这个序列中从左至右选若干个段,第i段的长度为i,对于任意的段i,段内元素和S[i]<S[i+1],求在该序列中最多可以选出几段. 思路:设dp[i][j]为 ...
- Scrapy(六):Spider
总结自:Spiders - Scrapy 2.5.0 documentation Spider 1.综述 ①在回调函数Parse及其他自写的回调函数中,必须返回Item对象.Request对象.或前两 ...