博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LA 3026 - Period KMP
阅读量:4684 次
发布时间:2019-06-09

本文共 1299 字,大约阅读时间需要 4 分钟。

看题传送门:

给定一个长度为n的循环节,求它的每个前缀的最短循环节。换句话说,对于每个i (2<=i<=n),求一个最大的整数K>1(如果k处在),使得s的前i个字符组成的前缀是某个字符串重复K次得到。输出所有存在K的i对应的K。

比如aabaabaabaab只有当 i=2 6 9 12时k存在,且分别为2,2,3,4

分析:

用KMP求得失配函数f为

j: 0  1  2  3  4  5  6  7  8  9  10  11  12

P a  a  b  a  a  b  a  a  b  a    a   b 

f 0  0  1  0  1   2  3  4  5  6    7  8    9

可以看出,如果它是一个循环节,那么有 i%(i-f[i])==0

为什么会这样?

KMP原来是模板串和文本串之间的匹配关系,而失配函数是模板串自身(将自身平移f[i],看是否能匹配)这题省略了文本串,可将文本串看做模板串,错位的部分即为i-f[i],如果这i 个组成循环节,那么 i - f[i]这部分必然也是循环节。

为什么这样?下面摘自

-----------------------

-----------------------

 k    m        x      j       i

由上,next【i】=j,两段红色的字符串相等(两个字符串完全相等),s[k....j]==s[m....i]

设s[x...j]=s[j....i](xj=ji)

则可得,以下简写字符串表达方式

kj=kx+xj;

mi=mj+ji;

因为xj=ji,所以kx=mj,如下图所示

 

-------------

      -------------

 k   m        x     j   

看到了没,此时又重复上面的模型了,kx=mj,所以可以一直这样递推下去

所以可以推出一个重要的性质len-next[i]为此字符串的最小循环节(i为字符串的结尾),另外如果len%(len-next[i])==0,此字符串的最小周期就为len/(len-next[i]);

#include
const int MAXN=1000000+10;char p[MAXN];int f[MAXN];void getfail(const int &n){ f[0]=f[1]=0; for(int i=1;i
0 && p[i]!=p[j]) j=f[j]; if(p[i]==p[j]) j++; f[i+1]=j; }}int main(){ int n; int kase=1; while(scanf("%d",&n),n) { scanf("%s",p); getfail(n); printf("Test case #%d\n",kase++); /* for(int i=0;i
0 && i%(i-f[i])==0) printf("%d %d\n",i,i/(i-f[i])); } printf("\n"); }}

转载于:https://www.cnblogs.com/murmured/p/5004268.html

你可能感兴趣的文章
文件I/O与标准I/O
查看>>
大数据学习之路(持续更新中...)
查看>>
项目开发总结报告(GB8567——88)
查看>>
enumerate使用
查看>>
神奇的位运算
查看>>
css 选择器优先级 pptx
查看>>
面试题总结101-)
查看>>
BZOJ1930: [Shoi2003]pacman 吃豆豆
查看>>
SSH加固
查看>>
端口扫描base
查看>>
Android自动更新安装后显示‘完成’‘打开’按钮
查看>>
C#反射技术概念作用和要点
查看>>
iOS IM开发的一些开源、框架和教程等资料
查看>>
2015年创业中遇到的技术问题:51-60
查看>>
FansUnion:共同写博客计划终究还是“流产”了
查看>>
中国象棋程序的设计与实现(六)--N皇后问题的算法设计与实现(源码+注释+截图)...
查看>>
mobiscroll 日期问题
查看>>
<jsp:include>和<%@include%>的区别
查看>>
poj 1691 搜索
查看>>
win7/win8下vmware/VirtualBox虚拟网卡显示未识别网络的解决
查看>>