017(Power Strings二刷)(KMP)
作者:互联网
题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1466
题目思路:不知道大家在KMP算法里有没有看见这么个句子
while(j<len)
这是找next数组的时候的游标范围
这说明 j 总有走到 len-1 的时候
但是这也说明了一个问题,next[len] 是一定有值的
要么 a[k]==a[j],要么就是 k 走到了-1
而我们今天要做的题就与这个被赋值的 next[len] 有关系
(注意:以下的两种情况都默认 j=len-1)
首先,如果是 k 走到了-1 这种情况
那next[len]会得零,这他妈跟没赋值有什么区别吗
接下来顺着另一种思路剖析
当 a[k]==a[j] 的时候可能会是
ACA
k j
或者
AABAABAAB
k j
。。。。。。数不过来
但是它也有规律可循
这边以X,Y,Z这三个大写字母为字符区块来推导
发现,k 永远是会离 j 所在的区块最近的一个相同区块的最后一个
比如
X X X Y X
此时的 k 会在第三个区块的最后一个
这是可以与 j 呼应上的
或者
Y Y Y Y
此时的 k 就会在第三个区块的最后一个字符上
接下来就是重点了
next[j] 是等于 k 的
并且由于区块相同
我是可以得到从 k+1~len-1 的这块,也就是最后一块区块的长度的
如果这种时候 len 还可以整除这个区块的长度的话
那不就是等于说:“嘿,前面的东西我都对应好了,你放心大胆的用!”
循环节以及循环节的个数,全部白给
#include<bits/stdc++.h> using namespace std; string a; int a0,qnext[1000001]; void hnext(string o,int o0){//next数组 int j=0,k=-1; qnext[j]=k; while(j<o0){ if(k==-1||o[j]==o[k]){ qnext[++j]=++k; } else{ k=qnext[k]; } } } int main(){ while(1){ cin>>a; if(a=="."){ return 0; } a0=a.size(); hnext(a,a0); if(a0%(a0-qnext[a0])==0){//能整除 printf("%d\n",a0/(a0-qnext[a0])); //白给 } else{//不能 printf("1\n"); //中间被某个B区块拦路了 //直接出1就得了 } } return 0; }
题目总结:这题的关键在于找到可能的循环节的长度
对某些模板程序探索一下会有意想不到的惊喜
标签:qnext,a0,int,len,next,二刷,KMP,区块,Strings 来源: https://www.cnblogs.com/a-001/p/16272759.html