Period next数组的应用

本文介绍了一种用于检测字符串前缀是否为周期串的算法,通过构造next数组来判断每个前缀是否存在周期性,并计算出最小周期的长度及数量。文章详细解析了next数组的生成过程及其在周期检测中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K,that is A concatenated K times, for some string A. Of course, we also want to know the period K.

输入:

The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line contains the string S. The input file ends with a line, having the 
number zero on it.

输出:

For each test case, output "Test case #" and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case.

样例输入:

3
aaa
12
aabaabaabaab
0

样例输出:

Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

这题就是给出一串字符,求前缀是周期串的长度,并且求出这个周期串有几个最小周期。例如abaaba是一个周期串,最小周期串是aba,一共有两个最小周期。

这道题主要是关于next数组的应用,以第二组案例为例。

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

a[i]     a   a   b   a   a   b   a   a   b   a    a     b

net[i]  -1  0   1   0   1   2   3   4   5   6    7     8     9

可以看出最小周期的长度时i-next[i],所以首先要判断i%(i-next[i])==0,并且题目中说这个长度K是大于1的,所以要满足i/(i-next[j])>1  (代码中的next数组用net表示,因为用next会显示标识符不明确)

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1000005;
char s[maxn];
int net[maxn];
int n;
void getnet()
{
    net[0]=-1;
    int j=0;
    int k=-1;
    while(j<n)
    {
        if(k==-1||s[j]==s[k])
        {
            ++j;
            ++k;
            net[j]=k;
        }
        else
            k=net[k];
    }
}
int main()
{
    int cas=1;
    while(scanf("%d",&n)!=EOF &&n)
    {
        scanf("%s",s);
        getnet();
        printf("Test case #%d\n",cas++);//不要忘记这一句
        for(int i=1;i<=n;i++)
        {
            int j=i-net[i];//最小周期的长度

            if(i%j==0&&i/j>1)//如果满足条件,就输出周期的最长度和最小周期的个数
            {
                printf("%d %d\n",i,i/j);
            }
        }
        printf("\n");
    }
    return 0;
}

 

module ws2812( input sysclk , input rst_n , output reg data_out ); parameter TIME_500us=15'd25_000; parameter PERIOD =60 ; reg [5:0] cnt ; reg [4:0] cnt_bit ; reg [5:0] cnt_pix ; wire data_done ; assign data_done=cnt=PERIOD-1&&cnt_bit==23&&cnt_pix==63 ; reg [23:0]data_reg ; reg cur_data ; wire [23:0]DATA [63:0] ;////定义64个位宽为24的数组 assign DATA[0]=24'hff_00_00 ;///绿 assign DATA[1]=24'h00_ff_00 ;///红 assign DATA[2]=24'h00_00_ff ;///蓝 parameter IDLE= 3'b001 ; parameter DATA_OUT=3'b010 ; parameter WAIT= 3'b100 ; reg [2:0]cur_state ; reg [2:0]next_state ; ///500us计时器 always@(posedge sysclk) if(!rst_n) cnt<=0 ; else if(cnt==TIME_500us-1) cnt<=0 ; else cnt<=cnt+1 ; ////周期计时器 always@(posedge sysclk) if(!rst_n) if(cnt==PERIOD-1) cnt<=0 ; end else cnt<=cnt+1 ; ////cnt_bit always@(posedge sysclk) if(!rst_n) cnt_bit<=0 ; else if(cnt==PERIOD-1)begin if(cnt_bit==23) cnt_bit<=0 ; else cnt_bit<=cnt_bit+1 ; end else cnt_bit<=cnt_bit ; ////cnt_pix always@(posedge sysclk) if(!rst_n) cnt_pix<=0 ; else if(cnt==PERIOD-1&&cnt_bit==23)begin if(cnt_pix==63) cnt_bit<=0 ; else cnt_pix=cnt_pix+1 ; end else cnt_pix<=cnt_pix ; ///data_reg always@(posedge sysclk) if(!rst_n) data_reg<=0 ; else data_reg<=DATA[cnt_pix] ; ///cur_data always@(posedge sysclk) if(!rst_n) cur_data<=0 ; else cur_data<=data_reg[23-cnt_bit] ; ///状态机 ///state1 always@(posedge sysclk) if(!rst_n) cur_state <= IDLE ; else cur_state <= next_state ; ///state2 always@(*) case(cur_state) IDLE:begin next_state = DATA_OUT ; end DATA_OUT:begin if(data_done) next_state = WAIT ; else next_state = cur_state ; end WAIT:begin if(cnt_pix==TIME_500us) next_state = DATA_OUT ; else next_state = cur_state ; end default:next_state=IDLE ; endcase ///state3 always@(posedge sysclk) if(!rst_n)begin 请帮我补全代码
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值