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当作自动机来跑

  


代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. #define inf 1e9
  7. using namespace std;
  8. struct SAM
  9. {
  10. int son[];
  11. }ch[];int cnt,dep[],a[],fail[],da[],la,root,ss;、
  12. //da 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度
  13. void add(int k)
  14. {
  15. int x=a[k];
  16. int p=la,np=++cnt;dep[np]=k;
  17. while(p!= && ch[p].son[x]==)ch[p].son[x]=np,p=fail[p];
  18. if(p==)fail[np]=root;
  19. else
  20. {
  21. int q=ch[p].son[x];
  22. if(dep[p]+==dep[q])fail[np]=q;
  23. else
  24. {
  25. int nq=++cnt;dep[nq]=dep[p]+;
  26. ch[nq]=ch[q];fail[nq]=fail[q];fail[np]=fail[q]=nq;
  27. while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=fail[p];
  28. }
  29. }
  30. la=np;
  31. }
  32. int len1,len2,opt;
  33. int c[],last[][];//位置i后面的第一个字符j
  34. char sa[],sb[];
  35. int f[][];//分别以i,j位置开头的最长公共前缀
  36. int main()
  37. {
  38. //freopen("a.in","r",stdin);
  39. //freopen("a.out","w",stdout);
  40. //scanf("%d",&opt);
  41. scanf("%s",sa+);len1=strlen(sa+);
  42. scanf("%s",sb+);len2=strlen(sb+);
  43. //if(opt==1)
  44. //{
  45. memset(f,,sizeof(f));int ans=inf,len=,maxx=;
  46. for(int i=len1;i>=;i--)for(int j=len2;j>=;j--)if(sa[i]==sb[j])f[i][j]=f[i+][j+]+;
  47. for(int i=;i<=len1;i++)
  48. {
  49. maxx=;for(int j=;j<=len2;j++)maxx=max(maxx,f[i][j]);
  50. if(maxx!=len1-i+)ans=min(ans,maxx+);//加一定不相等
  51. }
  52. if(ans==inf)printf("-1\n");
  53. else printf("%d\n",ans);
  54. //}
  55. //else if(opt==2)
  56. //{
  57. len=,ans=inf;for(int i=;i<=;i++)c[i]=inf;sb[]='a';
  58. for(int i=len2;i>=;i--){for(int j=;j<=;j++)last[i][j]=c[j];c[sb[i]-'a'+]=i;}
  59. for(int i=;i<=len1;i++)
  60. {
  61. len=;
  62. for(int j=i;j<=len1;j++)
  63. {
  64. len=last[len][sa[j]-'a'+];
  65. if(len>len1){ans=min(ans,j-i+);break;}//跳出去证明没有了
  66. }
  67. }
  68. if(ans==inf)printf("-1\n");
  69. else printf("%d\n",ans);
  70. //}
  71. // else if(opt==3)
  72. // {
  73. cnt=;root=la=++cnt;memset(da,,sizeof(da));
  74. for(int i=;i<=len2;i++)a[i]=sb[i]-'a';for(int i=;i<=len2;i++)add(i);ss=;da[]=;ans=inf;
  75. for(int i=;i<=len1;i++)
  76. for(int j=;j<=cnt;j++)
  77. {
  78. ss=ch[j].son[sa[i]-'a'];
  79. if(ss==)ans=min(ans,da[j]+);else da[ss]=min(da[ss],da[j]+);
  80. }
  81. if(ans==inf)printf("-1\n");
  82. else printf("%d\n",ans);
  83. // }
  84. //else if(opt==4)
  85. //{
  86. ans=inf;//for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a';
  87. //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;}
  88. memset(da,,sizeof(da));da[]=;ss=;
  89. for(int i=;i<=len1;i++)
  90. for(int j=len2;j>=;j--)
  91. {
  92. ss=last[j][sa[i]-'a'+];
  93. if(ss>len1)ans=min(ans,da[j]+);else da[ss]=min(da[ss],da[j]+);
  94. }
  95. if(ans==inf)printf("-1\n");
  96. else printf("%d\n",ans);
  97. //}
  98. return ;
  99. }

bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)的更多相关文章

  1. [BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)

    在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之——被它们虐. 操作一:对A,B分别建SAM,暴力BFS. 操作二:对B建序列自动机或SAM,A在上面暴力匹配. 操作三:对A,B建 ...

  2. BZOJ4032:[HEOI2015]最短不公共子串(SAM)

    Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...

  3. luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS

    luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...

  4. BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

  5. BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

  6. BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】

    题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...

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

  8. BZOJ4032 : [HEOI2015]最短不公共子串

    第一问: 对B串建立SAM,暴力枚举A的每个子串,在SAM上走,若失配则可行. 第二问: 设g[i][j]表示B串的第i个字符之后最早出现的字符j的位置,暴力枚举A的每个子串,按照g贪心地走,若失配则 ...

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

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

随机推荐

  1. H3BPM子表的复制

    在做一个流程的时候,碰到了下面的表数据直接从上表中获取,并且为不可编辑状态,没有增加和删除行的按钮.一开始使用的是ComputationRule属性,但是有一项是日期空间,没有这个属性,不知道怎么处理 ...

  2. guice基本使用,guice整合guice-servlet,web scope注解(六)

    guice servlet提供了几个比较有用的web scope,类似与传统servlet 的session,request这些提供的范围等. guice servlet 提供的web scope 如 ...

  3. Hibernate框架学习(十)——查询优化

    一.类级别查询 1.get方法:没有任何策略,调用即立即查询数据库加载数据. 2.load方法:是在执行时不发送任何SQL语句,返回一个对象,使用该对象时才执行查询:应用类级别的加载策略. 1> ...

  4. Robot Framework(三)创建测试用例

    2.2.1测试用例语法 基本语法 测试用例由关键字在测试用例表中构建.关键字可以从测试库或资源文件导入,也可以在测试用例文件本身的关键字表中创建. 测试用例表中的第一列包含测试用例名称.测试用例从包含 ...

  5. 【转】linux 增加用户 useradd 用法小结及配置文件说明

    原文地址:https://blog.csdn.net/warden2010/article/details/5132290 在Linux 系统中,所有的用户和组像一个国家.如果国家要繁荣昌盛的话,需要 ...

  6. matlab学习-使用自带的函数

    >> %定义矩阵求最大值>> a=[1 7 3;6 2 9];>> A=max(a);>> a a = 1 7 3 6 2 9 >> A A ...

  7. java中Map遍历的四种方式

    在java中所有的map都实现了Map接口,因此所有的Map(如HashMap, TreeMap, LinkedHashMap, Hashtable等)都可以用以下的方式去遍历. 方法一:在for循环 ...

  8. 小白学习Spark系列三:RDD常用方法总结

    上一节简单介绍了Spark的基本原理以及如何调用spark进行打包一个独立应用,那么这节我们来学习下在spark中如何编程,同样先抛出以下几个问题. Spark支持的数据集,如何理解? Spark编程 ...

  9. Vue学习之路第十五篇:v-if和v-show指令

    1.v-if和v-show都是用来实现条件判断的指令. 2.先看代码 <body> <div id="app"> <button @click=&qu ...

  10. Project Euler 23 Non-abundant sums( 整数因子和 )

    题意: 完全数是指真因数之和等于自身的那些数.例如,28的真因数之和为1 + 2 + 4 + 7 + 14 = 28,因此28是一个完全数. 一个数n被称为亏数,如果它的真因数之和小于n:反之则被称为 ...