zoukankan      html  css  js  c++  java
  • 【KMP】OKR-Periods of Words

    【KMP】OKR-Periods of Words

    题目描述

    串是有限个小写字符的序列,特别的,一个空序列也可以是一个串。一个串P是串A的前缀,当且仅当存在串B,使得A=PB。如果P≠A并且P不是一个空串,那么我们说P是A的一个proper前缀。
    定义Q是A的周期,当且仅当Q是A的一个proper前缀并且A是QQ的前缀(不一定要是proper前缀)。比如串abab和ababab都是串abababa的周期。串A的最大周期就是它最长的一个周期或者是一个空串(当A没有周期的时候),比如说,ababab的最大周期是abab。串abc的最大周期是空串。
    给出一个串,求出它所有前缀的最大周期长度之和。

    输入

    第一行一个整数k,表示串的长度。
    接下来一行表示给出的串。

    输出

    输出一个整数表示它所有前缀的最大周期长度之和。

    样例输入

    8
    babababa
    

    样例输出

    24

    提示

    对于全部数据,1<k<1e6


    【题意】:

    看题意,人话吗?我真的看了很久很久,最后还是找博客上的解释才看懂是什么 意思。。。

    参考博客:蒟蒻のblog


    思路

    先把题面转成人话:

    对于给定串的每个前缀i,求最长的,使这个字符串重复两边能覆盖原前缀i的前缀(就是前缀i的一个前缀),求所有的这些“前缀的前缀”的长度和

    利用nextnext的性质:前缀ii的长度为next[i]的前缀和后缀是相等的

    这说明:如果有i一个公共前后缀长度为j,那么这个前缀i就有一个周期为i-j

    见下图

    显然图中蓝色线段是黑色线段的一个周期

    那么接下来的问题就容易了:

    先求出next数组


    【代码】:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e6 + 10;
     4 typedef long long ll;
     5 char p[N];
     6 int Next[N],m;
     7 
     8 void get_Hash(){
     9     for(int i=2,j=0; i<=m;i++){
    10         while( j && p[i] != p[j+1] ) j = Next[j];
    11         if( p[i] == p[j+1] ) j++;
    12         Next[i] = j ;
    13     }
    14 }
    15 int main()
    16 {
    17     scanf("%d",&m);
    18     scanf("%s",p+1);
    19     ll ans = 0 ;
    20     get_Hash();
    21     for(int i=1;i<=m;i++){
    22         int j = i ;
    23         while( Next[j] ) j = Next[j];
    24         if( Next[i] ) Next[i] = j ;
    25         ans = ans + (i-j);
    26     }
    27     printf("%lld
    ",ans);
    28     return 0 ;
    29 }
    View Code
  • 相关阅读:
    Android 图表控件的使用
    使用kotlin开发android
    Servlet 使用介绍(3)
    Servlet 使用介绍(2)
    Servlet 使用介绍(1)
    Android 中的style和Theme的使用
    Java Web工程目录结构
    IP地址解析
    Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)
    Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)
  • 原文地址:https://www.cnblogs.com/Osea/p/11333584.html
Copyright © 2011-2022 走看看