10.6比赛 T3
丝(filament)
【题目描述】
小 H 对于毛线球情有独钟,这一天他从中抽出了一根丝。
他发现,丝可以被等分成 n 段,且每一段都有一种颜色 ai,而令
他惊奇的是,从这一段丝似乎可以看出颜色是有循环节的,而且是纯
循环,由此他推断整个毛线球就是一段 纯循环的颜色序列。假设小 H
抽出的这一根丝恰好是整团毛线的 一端, 他希望找出 可能的最小的循
环节。
【输入数据】
第一行一个正整数 T,表示数据组数。
接下来每两行表示一组数据:第一行一个正整数 n,表示丝的长
度;第二行 n 个整数,表示每一段的颜色, 规定第 1 段为整团毛线的
一端。
【输出数据】
输出共 T 行,对于每组数据,输出一行表示最小循环节长度。
【样例输入】
2
3
1 2 1
2
1 1
【样例输出】
2
1
【数据范围】
对于 20%的数据,n<=500;
对于 40%的数据,n<=2000;
另外 20%的数据,满足最小循环节长度整除 n。
对于 100%的数据,1<=T<=5,1<=T*n<=10^6,0<=|ai|<=10^9。
【样例解释】
第一组数据,循环节为 1 2,整团毛线可能是 1 2 1 2……。
第二组数据,循环节为 1,整团毛线可能是 1 1 1 1……。
思路:
用一个kmp将使用数从左到右过一遍,第一个搜到的数就是答案。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int t,n; 7 int a[1000001],x[1000001]; 8 int main() 9 { 10 int i,h; 11 //freopen("filament.in","r",stdin); 12 //freopen("filament.out","w",stdout); 13 cin>>t; 14 while(t--) 15 { 16 cin>>n; 17 for(i=1;i<=n;i++) 18 { 19 cin>>a[i]; 20 } 21 x[0]=-1; 22 h=-1; 23 for(i=1;i<=n;i++) 24 { 25 while(h>-1&&a[h+1]!=a[i]) 26 { 27 h=x[h]; 28 } 29 h++; 30 x[i]=h; 31 } 32 cout<<n-x[n]<<endl; 33 } 34 return 0; 35 }