【题意】给两个小写字母串A,B,请你计算:

(1) A的一个最短的子串,它不是B的子串

(2) A的一个最短的子串,它不是B的子序列

(3) A的一个最短的子序列,它不是B的子串

(4) A的一个最短的子序列,它不是B的子序列

不存在输出-1,1<=len(A),len(B)<=2000。

【算法】后缀自动机+序列自动机

【题解】虽然网上题解很多,但我总觉得这四个问题其实可以一个统一的形式来回答。因为字符串的自动机本质是相同的。

对串B建立后缀自动机来识别子串,建立序列自动机来识别子序列,从左到右枚举A串并在B自动机上进行。(序列自动机没有fail边,但这里不需要)

先考虑识别串A的子序列,设$f_x$表示自动机中节点x识别到的A的最短子序列。

对于A的子序列,从左到右枚举当前字母c,对B自动机中的每个节点都进行转移,假设x+c=y,那么:

$$f_y=min\{ f_y,f_x+1\}$$

如果y=null,那么贡献答案$ans=min\{ ans,f_x+1\}$。

原理是:字母c可以接在自动机识别了的所有子序列的后面形成新的子序列。

这里要注意更新顺序,为了满足无后效性,序列自动机要从后往前更新,后缀自动机要按Parent树从下往上更新(trans边不可能返祖)。

在考虑识别串A的子串,c只能接在所有以c前一位结尾的子串后面,那么只要每次转移到$f_y$时初始化$f_x=inf$即可。另外注意根节点不能置为inf(要接新子串)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,inf=0x3f3f3f3f;
int n,m,last,size,root,pre[maxn],ch[maxn][],f[maxn*],w[maxn],b[maxn*];
char s[maxn],a[maxn];
struct tree{int len,fa,t[];}t[maxn*];//
void insert_SAM(int c){
int np=++size;
t[np].len=t[last].len+;
int x=last;
last=np;
while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
if(!x)t[np].fa=root;else{
int y=t[x].t[c];
if(t[y].len==t[x].len+)t[np].fa=y;else{
int nq=++size;
t[nq]=t[y];//
t[nq].len=t[x].len+;
t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;//
}
}
}
void build(){
last=size=root=;
for(int i=;i<=m;i++)insert_SAM(s[i]-'a');
for(int i=;i<=m;i++){
int c=s[i]-'a';
for(int j=i-;j>=pre[c];j--)ch[j][c]=i;
pre[c]=i;
}
for(int i=;i<=size;i++)w[t[i].len]++;
for(int i=;i<=m;i++)w[i]+=w[i-];
for(int i=;i<=size;i++)b[w[t[i].len]--]=i;
}
int trans(int x,int c,int y){
if(!y)return t[x].t[c];
else return ch[x][c];
}
void solve(int A,int B){
memset(f,0x3f,sizeof(f));
f[B^]=;
int ans=inf;
for(int i=;i<=n;i++){
int c=a[i]-'a';
for(int z=(B?m:size);z>=(B^);z--){
int x=B?z:b[z];
int y=trans(x,c,B);
if(!y)ans=min(ans,f[x]+);else{
f[y]=min(f[y],f[x]+);if(!A&&x!=(B^))f[x]=inf;
}
}
}
printf("%d\n",ans==inf?-:ans);
}
int main(){
scanf("%s%s",a+,s+);n=strlen(a+);m=strlen(s+);
build();
solve(,);solve(,);solve(,);solve(,);
return ;
}

【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)的更多相关文章

  1. BZOJ 4032: [HEOI2015]最短不公共子串

    4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 446  Solved: 224[Submit][Sta ...

  2. BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力

    4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...

  3. bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...

  4. BZOJ.4032.[HEOI2015]最短不公共子串(DP 后缀自动机)

    题目链接 1.求A的最短子串,它不是B的子串. 子串是连续的,对B建SAM,枚举起点,在SAM上找到第一个无法匹配点即可.O(n)用SAM能做吗..开始想错了. 2.求A的最短子串,它不是B的子序列. ...

  5. 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] ...

  6. BZOJ 4032: [HEOI2015]最短不公共子串 (dp*3 + SAM)

    转博客大法好 第4个子任务中,为什么只转移最近的一个位置,自己YY吧(多YY有益身体健康). #include <bits/stdc++.h> using namespace std; t ...

  7. BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)

    传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...

  8. bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)

    4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...

  9. 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)

    [BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...

随机推荐

  1. laraven安装记录

    版本4.2.11 下载地址:https://codeload.github.com/laravel/laravel/zip/v4.2.11 步骤: 1.解压到目录 2.下载composer,并放到/u ...

  2. hdu-题目1159:Common Subsequence

    http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Oth ...

  3. TClientDataSet[5]: 读取数据

    本例用到: TClientDataSet.Fields[];          { 字段集合; 它比 FieldList 有更多功能, 如可获取嵌套字段 } TClientDataSet.FieldL ...

  4. DateTime Toxxx() 方法获取时间

    直接上代码 static void Main(string[] args) { DateTime time = DateTime.Now; Console.WriteLine("ToFile ...

  5. 第182天:HTML5——地理定位

    HTML5 Geolocation(地理定位) HTML5 Geolocation API 用于获得用户的地理位置. 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的. 浏览器支 ...

  6. 单源最短路径spfa模板(pascal)洛谷P3371

    题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...

  7. 详解SQL Server数据修复命令DBCC的使用

    严重级别为 21 表示可能存在数据损坏. 可能的原因包括损坏的页链.损坏的 IAM 或该对象的 sys.objects目录视图中存在无效条目. 这些错误通常由硬件或磁盘设备驱动程序故障而引起. MS ...

  8. Cells UVALive - 3486(dfs序+手动开栈)

    给一棵树,每次每次询问一个点是否是另一个点的祖先? 输入时是每个下标对应节点的儿子的数量 用dfs序 时间戳.. 如果一个点是另一个点的祖先,那么它的两个标记一定在祖先的范围之内 #include & ...

  9. MySQL用户授权

    一.授权语法格式  grant 权限列表 on 数据库名.表名 to '用户名'@'客户端主机' [identified by '密码']; 单词: privileges [ˈprivilidʒz] ...

  10. 【转载】 HDU 动态规划46题【只提供思路与状态转移方程】

    1.Robberies 连接 :http://acm.hdu.edu.cn/showproblem.php?pid=2955      背包;第一次做的时候把概率当做背包(放大100000倍化为整数) ...