[BOI2009] Radio Transmission 无线传输
题目描述
给你一个字符串 s 1 s_1 s1,它是由某个字符串 s 2 s_2 s2 不断自我连接形成的(保证至少重复 2 2 2 次)。但是字符串 s 2 s_2 s2 是不确定的,现在只想知道它的最短长度是多少。
输入格式
第一行一个整数 L L L,表示给出字符串的长度。
第二行给出字符串 s 1 s_1 s1 的一个子串,全由小写字母组成。
输出格式
仅一行,表示 s 2 s_2 s2 的最短长度。
样例 #1
样例输入 #1
8
cabcabca
 
样例输出 #1
3
 
提示
样例输入输出 1 解释
对于样例,我们可以利用 abc \texttt{abc} abc 不断自我连接得到 abcabcabc \texttt{abcabcabc} abcabcabc,读入的 cabcabca \texttt{cabcabca} cabcabca,是它的子串。
规模与约定
对于全部的测试点,保证 1 < L ≤ 1 0 6 1 < L \le 10^6 1<L≤106。
分析
#include<bits/stdc++.h>
using namespace std;
int m;
void getfail(char *p,int *f){
	m=strlen(p+1);
	f[1]=0;int j=0;
	for (int i=1;i<m;i++){
		while(j and p[j+1]!=p[i+1]) j=f[j];
		if (p[j+1]==p[i+1]) ++j;
		f[i+1]=j;
	}
	return;
}
char a[1000000];int f[100000];
int main(){
	cin>>a+1;
	getfail(a,f);
	for (int i=1;i<=m;i++) cout<<a[i]<<' ';
	cout<<endl;
	for (int i=1;i<=m;i++) cout<<i<<' ';
	cout<<endl;
	for (int i=1;i<=m;i++) cout<<f[i]<<' ';
	
	return 0;
} 
 
上面是一个推算过程,展现了KMP算法的预处理过程,譬如:
 
 这是原数组,下标,与失配的关系,具体可以说:我们输入字符串S,S具有一定的周期串T,那么对 
      
       
        
        
          m 
         
        
          − 
         
        
          f 
         
        
          [ 
         
        
          m 
         
        
          ] 
         
        
          , 
         
        
          m 
         
        
          = 
         
        
          ∣ 
         
        
          S 
         
        
          ∣ 
         
        
       
         m-f[m],m = |S| 
        
       
     m−f[m],m=∣S∣
 可以发现在此串中,周期串"ab"的长度为2,而 
     
      
       
       
         8 
        
       
         − 
        
       
         f 
        
       
         [ 
        
       
         8 
        
       
         ] 
        
       
      
        8-f[8] 
       
      
    8−f[8]也是为2,我们便得到了一个结论:
  
      
       
        
        
          m 
         
        
          − 
         
        
          f 
         
        
          [ 
         
        
          m 
         
        
          ] 
         
        
          = 
         
        
          ∣ 
         
        
          T 
         
        
          ∣ 
         
        
       
         m-f[m]=|T| 
        
       
     m−f[m]=∣T∣(想一想,为什么)
#include<bits/stdc++.h>
using namespace std;
int n,m;
void getfail(char *p,int *f){
	m=strlen(p+1);
	f[1]=0;int j=0;
	for (int i=1;i<m;i++){
		while(j>0 and p[j+1]!=p[i+1]) j=f[j];
		if (p[j+1]==p[i+1]) ++j;
		f[i+1]=j;
	}
	return;
}
void find(char *t,char *p,int *f,int &ans){
	getfail(p,f);
	int j=0;
	for (int i=0;i<n;i++){
		while(j>0 and p[j+1]!=t[i+1]) j=f[j];
		if (p[j+1]==t[i+1]) j++;
		if (m==j) 
		{	
			j=0;
			ans++;
		}
	}
}
char* a=new char[10000000];
int*  f=new int[10000000];
int main(){
	cin>>n;
	scanf("%s",a+1);
	getfail(a,f);
	cout<<n-f[n];
	return 0;
} 
 
通过此公式,便通过此题了





![[RocketMQ] Broker asyncSendMessage处理消息以及自动创建Topic (十)](https://img-blog.csdnimg.cn/da9f35d3bc66416a887cad2d23abd37d.png)













