【题意】给两个小写字母串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(要接新子串)。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int maxn=,inf=0x3f3f3f3f;
  6. int n,m,last,size,root,pre[maxn],ch[maxn][],f[maxn*],w[maxn],b[maxn*];
  7. char s[maxn],a[maxn];
  8. struct tree{int len,fa,t[];}t[maxn*];//
  9. void insert_SAM(int c){
  10. int np=++size;
  11. t[np].len=t[last].len+;
  12. int x=last;
  13. last=np;
  14. while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
  15. if(!x)t[np].fa=root;else{
  16. int y=t[x].t[c];
  17. if(t[y].len==t[x].len+)t[np].fa=y;else{
  18. int nq=++size;
  19. t[nq]=t[y];//
  20. t[nq].len=t[x].len+;
  21. t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
  22. while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;//
  23. }
  24. }
  25. }
  26. void build(){
  27. last=size=root=;
  28. for(int i=;i<=m;i++)insert_SAM(s[i]-'a');
  29. for(int i=;i<=m;i++){
  30. int c=s[i]-'a';
  31. for(int j=i-;j>=pre[c];j--)ch[j][c]=i;
  32. pre[c]=i;
  33. }
  34. for(int i=;i<=size;i++)w[t[i].len]++;
  35. for(int i=;i<=m;i++)w[i]+=w[i-];
  36. for(int i=;i<=size;i++)b[w[t[i].len]--]=i;
  37. }
  38. int trans(int x,int c,int y){
  39. if(!y)return t[x].t[c];
  40. else return ch[x][c];
  41. }
  42. void solve(int A,int B){
  43. memset(f,0x3f,sizeof(f));
  44. f[B^]=;
  45. int ans=inf;
  46. for(int i=;i<=n;i++){
  47. int c=a[i]-'a';
  48. for(int z=(B?m:size);z>=(B^);z--){
  49. int x=B?z:b[z];
  50. int y=trans(x,c,B);
  51. if(!y)ans=min(ans,f[x]+);else{
  52. f[y]=min(f[y],f[x]+);if(!A&&x!=(B^))f[x]=inf;
  53. }
  54. }
  55. }
  56. printf("%d\n",ans==inf?-:ans);
  57. }
  58. int main(){
  59. scanf("%s%s",a+,s+);n=strlen(a+);m=strlen(s+);
  60. build();
  61. solve(,);solve(,);solve(,);solve(,);
  62. return ;
  63. }

【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. java下执行mongodb

    1.1连单台mongodb Mongo mg = newMongo();//默认连本机127.0.0.1  端口为27017 Mongo mg = newMongo(ip);//可以指定ip 端口默认 ...

  2. 简述Java中Http/Https请求监听方法

    一.工欲善其事必先利其器 做Web开发的人总免不了与Http/Https请求打交道,很多时候我们都希望能够直观的的看到我们发送的请求参数和服务器返回的响应信息,这个时候就需要借助于某些工具啦.本文将采 ...

  3. 基于图形学混色问题OpenGl的收获

    void myDisplay(void) {glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_B ...

  4. linux php 访问sql server设置

    1.安装freeTDS wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-stable.tgz 1.1.进入到你下载的目录然后解压.tar - ...

  5. js & enter

    js & enter keycode function (e) { if (e.which === 13 || e.keyCode === 13) { //code to execute he ...

  6. ARP(Adress Resolution Protocol): 地址解析协议

    地址解析协议(Address Resolution Protoclol),其基本功能为通过目标设备的IP地址,查询目标设备的MAC地址,以保证通信的顺利.它是IPV4中网络层必不可少的协议.不过在IP ...

  7. 第124天:移动web端-Bootstrap轮播图插件使用

    Bootstrap JS插件使用 > 对于Bootstrap的JS插件,我们只需要将文档实例中的代码粘到我们自己的代码中> 然后作出相应的样式调整 Bootstrap中轮播图插件叫作Car ...

  8. 【Python】Python对象类型及其运算

    Python对象类型及其运算 基本要点: 程序中储存的所有数据都是对象(可变对象:值可以修改 不可变对象:值不可修改) 每个对象都有一个身份.一个类型.一个值 例: >>> a1 = ...

  9. bzoj2669-局部极小值

    题意 有一个 \(n\times m\) 的矩阵,其中每个数都是 \([1,n\times m]\) 中的一个,不会重复.有一些地方的值比周围的8个位置都小(如果有的话).给出这些位置,求这样的矩阵有 ...

  10. 【JavaScript】时间戳转日期格式

    时间戳: 1480570979000 $.ajax({ url : "getOrderMsg?shiplabel="+ shiplabel, type : "get&qu ...