热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

bzoj3277串&&bzoj3473字符串&&bzoj2780[Spoj]8093SevenkLoveOimaster——广义后缀自动机

题目:https:www.lydsy.comJudgeOnlineproblem.php?id3277https:www.lydsy.comJudgeOnlineprobl

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277

   https://www.lydsy.com/JudgeOnline/problem.php?id=3473

学习的博客:https://www.cnblogs.com/HocRiser/p/9580478.html

广义后缀自动机有两种写法,这里写的是 trie 树的那种。

大意就是每个串从自动机的根开始走,

1.如果存在 q = go[p][w] ,且 l [q] == l [p]+1 ,  那么直接把 q 看作这次插入了的点,下次令 p = q ,续着往后插入;

2.如果存在 q = go[p][w] ,且 l [q] != l [p]+1 , 那么分出一个 nq 来,把 nq 看作这次插入了的点,下次令 p = nq ,续着往后插入;

3.如果不存在 q = go[p][w] ,就新建一个 np ;然后就是一个串的后缀自动机插入了;下次令 p = np 。

要计算后缀自动机上的每个点代表的那些子串在所有串里出现了多少次,记为 ct[ ] ;

  在做一个串的插入的时候,考虑让一些位置的 ct[ ] ++ ;每插入一个字符,就跳 fa ,给所有 fa 的 ct[ ] ++ ;但如果已经被当前字符串的之前字符弄得 ct[ ] 加一过了,就不用再加了;

  不要边建自动机边做 ct[ ] ++ ;因为那时的 parent 树还不是所有串的。

然后拓扑排序一下,从根到叶子做 dp ,自己节点可以贡献的合法子串个数 ans[ ] 就是 ans[ fa ] 再加上 “ 自己出现了 >= k 次?l [cr] - l [fa] : 0 ” 。

两道题用同样的代码即可。

#include
#include
#include<string>//
#include
#define ll long long
using namespace std;
int Mx(int a,int b){return a>b?a:b;}
const int N=1e5+5,M=N<<1,K=27;//<<1
int n,k,go[M][K],l[M],fa[M],tot=1;
int tx[M],q[M],ans[M],ct[M],vis[M];
int cz(int p,int w)
{
  int q=go[p][w],nq=++tot;l[nq]=l[p]+1;
  fa[nq]=fa[q];fa[q]=nq;
  memcpy(go[nq],go[q],sizeof go[q]);
  for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
  return nq;
}
int ins(int p,int w)
{
  if(go[p][w])
    {
      int q=go[p][w];
      if(l[q]==l[p]+1)return go[p][w];
      else return cz(p,w);//////
    }
  else
    {
      int np=++tot;l[np]=l[p]+1;
      for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
      if(!p)fa[np]=1;
      else
    {
      int q=go[p][w];
      if(l[q]==l[p]+1)fa[np]=q;
      else fa[np]=cz(p,w);
    }
      return np;
    }
}
void Rsort(int mxn)
{
  for(int i=1;i<=tot;i++)tx[l[i]]++;
  for(int i=1;i<=mxn;i++)tx[i]+=tx[i-1];
  //  for(int i=tot;i;i--)q[tx[l[i]]--]=i;
  for(int i=1;i<=tot;i++)q[tx[l[i]]--]=i;
}
string ch[N]; int len[N];
int main()
{
  scanf("%d%d",&n,&k); char tp[N]; int mxn=0;
  for(int i=1,d;i<=n;i++)
    {
      scanf("%s",tp);len[i]=strlen(tp);mxn=Mx(mxn,len[i]);
      ch[i]=tp;
    }
  for(int i=1;i<=n;i++)
    for(int lm=len[i],pr=1,j=0;j)
      pr=ins(pr,ch[i][j]-'a'+1);
  for(int i=1;i<=n;i++)
    for(int lm=len[i],cr=1,j=0;j)
      {
    cr=go[cr][ch[i][j]-'a'+1];
    for(int p=cr;p&&vis[p]!=i;p=fa[p])
      ct[p]++,vis[p]=i;
      }
  Rsort(mxn);
  for(int i=2,d;i<=tot;i++)
    {d=q[i];ans[d]=ans[fa[d]]+(ct[d]>=k?l[d]-l[fa[d]]:0);}//
  for(int i=1;i<=n;i++)
    {
      ll prn=0;
      for(int lm=len[i],cr=1,j=0;j)
    {
      cr=go[cr][ch[i][j]-'a'+1];
      prn+=ans[cr];
    }
      printf("%lld ",prn);
    }
  puts("");return 0;
}
View Code

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2780

和上一道题一样。

#include
#include
#include
#include<string>
using namespace std;
int const xn=2e5+5;
const int N=1e4+5,M=2e5+5,N2=4e5+5,K=27;
int n,go[M][K],fa[M],l[M],ct[M],tot=1;
string s[N];int len[N],vis[M];
int cz(int p,int w)
{
  int q=go[p][w],nq=++tot; l[nq]=l[p]+1;/////////l[p]+1 not l[q]+1!!!!!
  fa[nq]=fa[q];fa[q]=nq;
  memcpy(go[nq],go[q],sizeof go[q]);
  for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
  return nq;
}
int ins(int p,int w)
{
  if(go[p][w])
    {
      int q=go[p][w];
      if(l[q]==l[p]+1)return q; else return cz(p,w);
    }
  else
    {
      int np=++tot;l[np]=l[p]+1;
      for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
      if(!p)fa[np]=1;
      else
    {
      int q=go[p][w];
      if(l[q]==l[p]+1)fa[np]=q; else fa[np]=cz(p,w);
    }
      return np;
    }
}
char ch[N2]; int Q;
int main()
{
  scanf("%d%d",&n,&Q);
  for(int i=1;i<=n;i++)
    {
      scanf("%s",ch);len[i]=strlen(ch);
      s[i]=(string)ch;
      for(int pr=1,j=0,lm=len[i];j)
    pr=ins(pr,ch[j]-'a'+1);
    }
  for(int i=1;i<=n;i++)
    for(int cr=1,j=0,lm=len[i];j)
      {
    cr=go[cr][s[i][j]-'a'+1];
    for(int p=cr;p>1&&vis[p]!=i;p=fa[p])
      ct[p]++,vis[p]=i;
      }
  while(Q--)
    {
      scanf("%s",ch);int lm=strlen(ch),cr=1;
      for(int j=0;j)
    cr=go[cr][ch[j]-'a'+1];
      printf("%d\n",ct[cr]);
    }
  return 0;
}
View Code

 


推荐阅读
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 题目《BZOJ2654: Tree》的时间限制为30秒,内存限制为512MB。该问题通过结合二分查找和Kruskal算法,提供了一种高效的优化解决方案。具体而言,利用二分查找缩小解的范围,再通过Kruskal算法构建最小生成树,从而在复杂度上实现了显著的优化。此方法不仅提高了算法的效率,还确保了在大规模数据集上的稳定性能。 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 在C#中,一旦对象被实例化后,直接重新调用构造函数是不可行的。与C++不同,C#不支持在对象实例化后强制调用构造函数。为了实现类似的功能,可以通过定义一个重置方法或使用工厂模式来重新初始化对象的状态。例如,可以创建一个 `Reset` 方法,在该方法中重新设置对象的属性和状态,从而达到类似于重新调用构造函数的效果。这样不仅保持了代码的清晰性和可维护性,还避免了潜在的副作用。 ... [详细]
  • 在C++程序中,文档A的每一行包含一个结构体数据,其中某些字段可能包含不同数量的数字。需要将这些结构体数据逐行读取并存储到向量中,随后不仅在控制台上显示,还要输出到新创建的文档B中。希望得到指导,感谢! ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 在iOS开发中,`UIScrollView` 的滚动条显示与隐藏由两个关键属性控制,默认情况下,滚动条会在滚动时短暂显示,然后自动消失。通过设置 `showsHorizontalScrollIndicator` 和 `showsVerticalScrollIndicator` 属性为 `YES` 或 `NO`,可以强制始终显示或隐藏水平和垂直滚动条。此外,还可以通过 `indicatorStyle` 属性调整滚动条的样式,以适应不同的界面需求。这些属性的灵活运用能够显著提升用户体验。 ... [详细]
  • 在探讨如何在Android的TextView中实现多彩文字与多样化字体效果时,本文提供了一种不依赖HTML技术的解决方案。通过使用SpannableString和相关的Span类,开发者可以轻松地为文本添加丰富的样式和颜色,从而提升用户体验。文章详细介绍了实现过程中的关键步骤和技术细节,帮助开发者快速掌握这一技巧。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • MSP430F5438 ADC12模块应用与学习心得
    在最近的实践中,我深入研究了MSP430F5438的ADC12模块。尽管该模块的功能相对简单,但通过实际操作,我对MSP430F5438A和MSP430F5438之间的差异有了更深刻的理解。本文将分享这些学习心得,并探讨如何更好地利用ADC12模块进行数据采集和处理。 ... [详细]
  • 在《ChartData类详解》一文中,我们将深入探讨 MPAndroidChart 中的 ChartData 类。本文将详细介绍如何设置图表颜色(Setting Colors)以及如何格式化数据值(Formatting Data Values),通过 ValueFormatter 的使用来提升图表的可读性和美观度。此外,我们还将介绍一些高级配置选项,帮助开发者更好地定制和优化图表展示效果。 ... [详细]
author-avatar
alilx
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有