[Baltic2009]Radio Transmission--bzoj1335(题解)

题目描述


给你一个字符串,它是由某个字符串不断自我连接形成的。
但是这个字符串是不确定的,现在只想知道它的最短长度是多少.

这里写图片描述

题解


这是一道结论题: n n e x t [ n ]
那么怎么证明呢??

我们把文本T与next[n] 取出来并且开头对齐,如图:
这里写图片描述
此时相同位置的字符是相同的。
因为题目告诉我们文本串是由一个某个字符串不断自我连接形成的。
那么 T n e x t [ n ] n e x t [ n ] 的开头是一样的
将所对应的回到文本T上去,在回到next上,这样反复对应,我们发现 T n e x t [ n ] 可以用 T n e x t [ n ] 填充满,所以 T n e x t [ n ] 一定是文本串的循环节。
那么如何证明 T n e x t [ n ] 是最短的循环节呢,我们回忆一下next数组的定义,如果存在比 T n e x t [ n ] 更短的循环节的话,next会更长,所以 T n e x t [ n ] 是最短的。

代码:

//By Bibi
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=1000010;
int len;
int next[MAXN];
int read(){
    int sum=0,flag=1;
    char c;
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
    for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
    return sum*flag;
}
int n;
char s[MAXN];
void init(){
    n=read();
    scanf("%s",s+1);
    len=strlen(s+1);
}
void yuchuli(){
    int j=0;
    next[1]=0;
    rep(i,2,len){
        while(j&&s[i]!=s[j+1]) j=next[j];
        if(s[i]==s[j+1]) ++j;
        next[i]=j;
    }
}
int main(){
    init();
    yuchuli();
    printf("%d",n-next[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/bbbblzy/article/details/79833928
今日推荐