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


php

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  

                        ios

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

  注意:因爲輸出次數太多 (2 <= N <= 1 000 000),建議用printf輸出,不然會超時。數組

  代碼:spa

 

 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/yym2013code

相關文章
相關標籤/搜索