传送门

解题思路

  首先需要预处理两个串$nxt(i)(j)$表示i位置之后最近的$j$。
  第一问直接对$b$建后缀自动机,枚举$a$的起点暴力匹配。
  第二问枚举$a$的起点,$b$用$nxt$跳。
  第三问$a$与$b$一起跳,$b$用后缀自动机,$a$用$nxt$。
  第四问$a$与$b$一起跳,都用$nxt$,要加记忆化。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm> using namespace std;
const int N=2005; inline int min(int x,int y) {return x<y?x:y;} int lena,lenb,ans=1e9,nxta[N][27],prea[27],nxtb[N][27],preb[27];
int vis[N][N];
char A[N],B[N]; struct SAM{
int lst,cnt,fa[N<<1],ch[N<<1][27],l[N<<1];
inline void insert(int c){
int p=lst,np=++cnt; lst=cnt; l[np]=l[p]+1;
for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(l[q]==l[p]+1) fa[np]=q;
else {
int nq=++cnt; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
}
inline int query1(int x){
int p=1,ret=0;
for(int i=x;i<=lena;i++) {
if(ch[p][A[i]-'a']) p=ch[p][A[i]-'a'],ret++;
else return ret+1;
}
return 1e9;
}
inline void query3(int x,int y,int l){
for(int i=0;i<26;i++){
if(!ch[y][i] && nxta[x][i]) ans=min(ans,l);
else if(ch[y][i] && nxta[x][i]) query3(nxta[x][i],ch[y][i],l+1);
}
}
}sam; inline int query2(int x){
int now=0,ret=0;
for(int i=x;i<=lena;i++){
if(!nxtb[now][A[i]-'a']) return ret+1;
ret++; now=nxtb[now][A[i]-'a'];
}
return 1e9;
} int query4(int x,int y){
if(x && !y) return 1;
if(vis[x][y]) return vis[x][y];
int tmp=1e9;
for(int i=0;i<26;i++){
if(!nxta[x][i]) continue;
tmp=min(tmp,query4(nxta[x][i],nxtb[y][i]));
}
vis[x][y]=tmp+1;
return vis[x][y];
} int main(){
scanf("%s%s",A+1,B+1); sam.cnt=sam.lst=1;
lena=strlen(A+1); lenb=strlen(B+1);
for(int i=lena;~i;i--) {
for(int j=0;j<26;j++) nxta[i][j]=prea[j];
prea[A[i]-'a']=i;
}
for(int i=lenb;~i;i--){
for(int j=0;j<26;j++) nxtb[i][j]=preb[j];
preb[B[i]-'a']=i;
}
for(int i=1;i<=lenb;i++) sam.insert(B[i]-'a');
for(int i=1;i<=lena;i++) ans=min(ans,sam.query1(i));
printf("%d\n",(ans==1e9)?-1:ans); ans=1e9;
for(int i=1;i<=lena;i++) ans=min(ans,query2(i));
printf("%d\n",(ans==1e9)?-1:ans); ans=1e9; sam.query3(0,1,0);
printf("%d\n",(ans==1e9)?-1:ans+1); ans=query4(0,0)-1;
printf("%d\n",(ans==1e9)?-1:ans);
return 0;
}

BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)的更多相关文章

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

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

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

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

  3. bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)

    bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...

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

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

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

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

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

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

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

  8. bzoj 4032 [ HEOI 2015 ] 最短不公共子串 —— 后缀自动机+序列自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 序列自动机其实就是每个位置记录一下某字母后面第一个出现位置,为了子序列能尽量长. 对字 ...

  9. 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

    [题意]给两个小写字母串A,B,请你计算: (1) A的一个最短的子串,它不是B的子串 (2) A的一个最短的子串,它不是B的子序列 (3) A的一个最短的子序列,它不是B的子串 (4) A的一个最短 ...

随机推荐

  1. sonarqube6.7.1使用

    1.插件安装 方法1.登入sonarqube-web安装 admin/admin 配置--应用市场--全部 英文片:administration--configuration--marketplace ...

  2. 自动收集有效IP代理

    自动收集有效IP代理 #需要的外部依赖包requests和lxml#自动获取的代理ip数据保存为”IP代理池.txt“#read_ip函数用于提取”IP代理池.txt“的数据返回类型为列表from l ...

  3. mysql 查询结果增加自动递增的一列,排名,排序

      mysql中有时候需要对查询的结果排序,比如根据成绩获取排名信息等,需要增加一个自增的列,也就是排名信息 ; as sortid FROM a; 如果不支持写两条sql,可以用以下写法合成一条sq ...

  4. leetcode-解题记录 771. 宝石与石头

    题目: 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头. S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石. J 中的字母不重复,J 和 S中的所有字符 ...

  5. C++ 常见的cin的错误处理

    写程序时想要用 cin 对输入的合法性检查,于是学习了一下 cin.fail() 函数,顺便学习了类似的一些函数. cin 对象包含了一个描述流状态的数据成员.流状态有 3 个标志位:eofbit,b ...

  6. BootStrap的一些基本语法

    一, 1.@using :引入命名空间 2.@model:声明强类型的数据 Model 类型 3.@section:定义要实现母版页的节信息 4.@RenderBody():当创建基于此布局页面的视图 ...

  7. MongoDB Windows之ZIP安装

    下载.下载地址同MSI下载地址:https://www.mongodb.com/download-center/community .Package选择Zip. 下载完成后解压到对应文件夹,该文件夹就 ...

  8. C++中的静态成员函数

    1,问完成的需求: 1,统计在程序运行期间某个类的对象数目: 1,静态成员变量满足了这个需求: 2,保证程序的安全性(不能使用全局变量): 3,随时可以获取当前对象的数目: 1,有没有什么特别的地方或 ...

  9. 推荐系统之隐语义模型LFM

    LFM(latent factor model)隐语义模型,这也是在推荐系统中应用相当普遍的一种模型.那这种模型跟ItemCF或UserCF的不同在于: 对于UserCF,我们可以先计算和目标用户兴趣 ...

  10. 【UR #5】怎样跑得更快

    题目 给定\(n,c,d\)和序列\(\{b_i\}\),求一个序列\(\{x_i\}\)满足 \[\sum_{j=1}^n\gcd(i,j)^c\times \rm{lcm(i,j)^d}\time ...