标签:n+1 get some pst scan 表示 out class course
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 20436 | Accepted: 9961 |
Description
Input
Output
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
Source
题意:
求一个字符串的所有前缀的最短循环节。
思路:
首先,一个字符串要是可以由他的子串循环而成的话,那么这个字符串的长度一定是子串长度len的倍数。并且一定有S[len+1 ~ i] = S[1 ~ i- len]
而KMP求出的nxt数组,表示的就是对于每一个i,S[i - nxt[i] + 1 ~ i] = S[1 ~ nxt[i]]
因此,当i - nxt[i]能整除i时,S[1 ~ i - nxt[i]]就是S[1 ~ i]的最小循环元。
1 #include <iostream> 2 #include <set> 3 #include <cmath> 4 #include <stdio.h> 5 #include <cstring> 6 #include <algorithm> 7 #include <map> 8 using namespace std; 9 typedef long long LL; 10 #define inf 0x7f7f7f7f 11 12 int n; 13 const int maxn = 1e6 + 5; 14 int nxt[maxn]; 15 char s[maxn]; 16 17 void getnxt() 18 { 19 nxt[1] = 0; 20 for(int i = 2, j = 0; i <= n; i++){ 21 while(j > 0 && s[i] != s[j + 1]){ 22 j = nxt[j]; 23 } 24 if(s[i] == s[j + 1])j++; 25 nxt[i] = j; 26 } 27 } 28 29 int main() 30 { 31 int cas = 1; 32 while(scanf("%d", &n) != EOF && n){ 33 scanf("%s", s + 1); 34 getnxt(); 35 printf("Test case #%d\n", cas++); 36 for(int i = 1; i <= n; i++){ 37 if(i % (i - nxt[i]) == 0 && i / (i - nxt[i]) > 1){ 38 printf("%d %d\n", i, i / (i - nxt[i])); 39 } 40 } 41 printf("\n"); 42 } 43 return 0; 44 }
标签:n+1 get some pst scan 表示 out class course
原文地址:https://www.cnblogs.com/wyboooo/p/9821684.html