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 $ ,请你计算: ...
随机推荐
- ACM_支离破碎(递推dp)
支离破碎 Time Limit: 4000/2000ms (Java/Others) Problem Description: 远古时期有一位魔王想向一座宫殿里的公主求婚.为了考验魔王的智力,太后给了 ...
- 使用C#正则表达式获取必应每日图片地址
微软的Bing搜索引擎首页每天都会提供了一些有趣的图片,下面使用正则表达式获取图片的地址,不管是在手机app还是在网站上都是很好的图片素材,而且每天更新,非常不错. 首先访问微软的API,该地址返回的 ...
- MemCached总结一:Unbutu操作系统下memcached服务器安装和telnet方式连接memcache
1.在Unbutu上安装memcached服务器 sudo apt-get update sudo apt-get install memcached 2. 确认memcached是否安装 要确认me ...
- Nginx代码风格图示
Nginx代码风格图示 (100%) 一.基本原则 K&R编码风格(偏BSD子类). 每行不能超过80列. 不用TAB对齐,用空格. 默认对齐单元是4个空格. 除宏定义外,字母均为小写,单词间 ...
- 用JS解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题
当用ajax异步时,返回JsonResult格式的时候,发现当字段是dateTime类型时,返回的json格式既然是“/Date(1435542121135)/” 这样子的,当然这不是我们想要的格式. ...
- ML一:python的KNN算法
(1):list的排序算法: 参考链接:http://blog.csdn.net/horin153/article/details/7076321 示例: DisListSorted = sorted ...
- jQuery删除元素
remove() - 删除被选元素(及其子元素) empty() - 从被选元素中删除子元素 $("#div1").remove();删除被选元素及其子元素. $("#d ...
- Elasticsearch学习(一)————简单命令
Elasticsearch一.简介**Elasticsearch 是一个分布式的搜索和分析引擎,可以用于全文检索.结构化检索和分析,并能将这三者结合起来.Elasticsearch 基于 Lucene ...
- CF div2 499 A. Stages
Code: #include<cstdio> #include<algorithm> #include<iostream> using namespace std; ...
- NYOJ-1013除法表达式
除法表达式 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 给出一个这样的除法表达式:X1/X2/X3/···/Xk,其中Xi是正整数.除法表达式应当按照从左到右的顺 ...