标签:
秋实大哥是一个多愁善感的人,偶尔也会唱唱两句伤情的歌。每次唱完后,秋实大哥都能解决一道问题!这次也不例外。
秋实大哥告诉了你 一些关于这个问题的信息
如果一个字符串S是由若干个子串a连续拼接而成的,则称a是S的循环节,即A=a+a+...+a。比如 aba 是 abaabaaba 的循环节。
一个字符串可能存在多个循环节,比如 aaaaaaaa ,含有4个循环节,分别是 a , aa , aaaa , aaaaaaaa 。很显然,一个字符串是其本身的循环节。在这4个循环节中,长度最小的是"a",所以"a"是S的最小循环节。
字符串所有循环节里长度最小的循环节,就是该字符串的最小循环节。
一个长度为N的字符串,含有N个非空前缀。定义P(i)表示S的第i个非空前缀(0≤i<|S|),P(i)=S012...i。比如"abcde"含有5个非空前缀,分别是"a",“ab”,“abc”,“abcd”,“abcde”。
秋实大哥唱完了,问题也解决了,现在他请你来解决这个问题。
第一行输入一个字符串S(0<|S|≤3⋅106),S只含有小写英文字母(a-z)
第一行输出 |S| 个数,分别表示S的每一个非空前缀的最小循环节的长度,每两个数用一个空格隔开,最后一个数后面不要有空格。
第二行输出一个字符串,表示S的最小循环节。
Sample Input | Sample Output |
---|---|
ab |
1 2 ab |
aaaaaaaaa |
1 1 1 1 1 1 1 1 1 a |
aaaaaaaad |
1 1 1 1 1 1 1 1 9 aaaaaaaad |
abbaaddaabbaadda |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 8 abbaadda |
abbaabbaabbaabba |
1 2 3 4 5 6 7 4 9 10 11 4 13 14 15 4 abba |
解题报告:
这是一道求最小循环节题目
关键在于了解next数组的含义,next[i] 表示 0 - i-1的最大前缀后缀最大值,我们先假设它是循环的,那么显然满足i % (i - next[i]) == 0 , ( 长度是整数倍 ),之后next[i] != 0 (若为 0 ,此时前缀后缀的长度最大值0,也就是说,就是本身)
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int maxn = 3e6 + 500; char s[maxn]; int len,front[maxn]; void build_front() { front[0] = -1; int t1 = -1,t2 = 0; while(t2 < len) { if (t1 == -1 || s[t1] == s[t2]) front[++t2] = ++ t1; else t1 = front[t1]; } } int main(int argc,char *argv[]) { scanf("%s",s); len = strlen(s); build_front(); printf("1"); for(int i = 2 ; i <= len ; ++ i) if (i % (i-front[i]) == 0 && front[i] != 0 ) printf(" %d",i-front[i]); else printf(" %d",i); printf("\n"); if (len % (len-front[len]) == 0 && front[len] != 0) { int cot = len - front[len]; for(int i = 0 ; i < cot ; ++ i) printf("%c",s[i]); } else printf("%s",s); printf("\n"); return 0; }
UESTC_全都是秋实大哥 2015 UESTC Training for Search Algorithm & String<Problem J>
标签:
原文地址:http://www.cnblogs.com/Xiper/p/4499176.html