zoukankan      html  css  js  c++  java
  • 【ybtoj】【kmp】周期长度和

    推荐一篇dalao写的博客:wind_whisper

    题意

    题解

    首先想想题里说的周期和kmp里的 nxt 数组有没有什么关系

    对于一个长度为 i 的串,i - nxt[i]就是一个周期的长度(不一定最大)

    假设 i - nxt[i] > i/2 ,即一个串的最短(前缀=后缀)的长度一定小于等于这个串的一半

    可以想象,把一个串的 1 ~ i - nxt[i] 的部分复制一倍接在后面,一定能使原来的整串成为新的串的前缀

    但是 i - nxt[i] <i/2 的话,显然长度上就不满足,但这种情况(即一个串的最短(前缀=后缀)的长度一大于这个串的一半)是不存在的,具体见下图

    (假设黑色的部分是最短的(前缀=后缀),就能证明出还存在更短的红色部分(前缀=后缀))

    在这里插入图片描述

    同时,这里连续跳 nxt 数组的过程可以用类似并查集路径压缩的方式优化,值得学习

    代码

    周期长度和
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 1e6+10;
    int nxt[N],n;
    ll ans;
    char s[N];
    void pre()
    {
    	int j=0;
    	nxt[1]=0;
    	for(int i=1;i<n;i++)	
    	{
    		while(s[i+1]!=s[j+1]&&j) j=nxt[j];
    		if(s[i+1]==s[j+1]) j++;
    		nxt[i+1]=j;
    	}
    }
    int find(int x)
    {
    	if(nxt[x]) return nxt[x]=find(nxt[x]);
    	return x;
    int main()
    {
    	scanf("%d%s",&n,s+1);
    	pre();
    	for(int i=1;i<=n;i++)	
    		ans+=i-find(i);
    		//(我原本从nxt[i]开始错了)从i开始,因为当nxt[i]==0时没有周期 
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    min25筛
    ngnix安装
    Sublime Text 添加到右键菜单 带菜单图标
    临界区与竟态条件
    cscope 支持C++项目
    内网信息收集
    域权限维持-Hook PasswordChangeNotify
    域权限维持-SID History
    域权限维持-DSRM
    ZooKeeper
  • 原文地址:https://www.cnblogs.com/conprour/p/15234063.html
Copyright © 2011-2022 走看看