hdu 1358:Period(KMP算法,next[]數組的使用)


Period

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2398    Accepted Submission(s): 1187


Problem Description
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.
 

 

Input
The input file 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.
 

 

Output
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.
 

 

Sample Input
3
aaa
12
aabaabaabaab
0
 

 

Sample Output
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4
 

 

Recommend
JGShining   |   We have carefully selected several similar problems for you:   1711  1686  3746  3068  2203 
 
  KMP算法。
  這道題考察的是KMP算法中next數組的應用,必須理解透next[]數組代表的含義才能通過它解決這道題。
  思路是先構造出 next[] 數組,下標為 i,定義一個變量 j = i - next[i] 就是next數組下標和下標對應值的差,如果這個差能整除下標 i,即 i%j==0 ,則說明下標i之前的字符串(周期性字符串長度為 i)一定可以由一個前綴周期性的表示出來,這個前綴的長度為剛才求得的那個差,即 j,則這個前綴出現的次數為 i/j 。所以最后輸出i和i/j即可。
 
  舉這道題的第二組輸入樣例為
  其next[]數組為:
 i 0  1  2  3  4  5  6  7  8  9  10 11 a[i] a a b a a b a a b a a b next[i] -1  0  1  0  1  2  3  4  5  6  7  8  

                        

  next[i]值是0或-1的忽略。

  注意:由於輸出次數太多 (2 <= N <= 1 000 000),建議用printf輸出,否則會超時。

  代碼:

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;  4 char a[1000010];  5 int next[1000010];  6 int n;  7 void GetNext()    //獲得a數列的next數組
 8 {  9     int i=0,k=-1; 10     next[0] = -1; 11     while(i<n){ 12         if(k==-1){ 13             next[i+1] = 0; 14             i++;k++; 15  } 16         else if(a[i]==a[k]){ 17             next[i+1] = k+1; 18             i++;k++; 19  } 20         else
21             k = next[k]; 22  } 23 } 24 void DisRes(int num) 25 { 26     int j; 27     printf("Test case #%d\n",num); 28     for(int i=0;i<=n;i++){ 29         if(next[i]==-1 || next[i]==0)   //next[i]是-1或0的忽略,說明之前沒有周期性前綴
30             continue; 31         j = i - next[i]; 32         if(i%j==0)  //能整除,說明存在周期性前綴
33             printf("%d %d\n",i,i/j);    //輸出這個前綴的長度和周期數
34  } 35     printf("\n"); 36 } 37 int main() 38 { 39     int num = 0; 40     while(scanf("%d",&n)!=EOF){ 41         if(n==0) break; 42         scanf("%s",a); 43         GetNext();  //獲得next[]數組
44         DisRes(++num);  //輸出結果
45  } 46     return 0; 47 }

 

Freecode : www.cnblogs.com/yym2013


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM