hdu oj Period (kmp的应用)

Period

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 2866    Accepted Submission(s): 1433

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 AK , 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

这道题開始看了好久都没懂题意,后来对着例子看了一下,把题意大体弄懂了,就是给你一个字符串。求里面的循环节的个数。从第二个字符開始,推断是否是循环串,并求出循环的周期(出现的次数)。然后我自己想開始想到字符串匹配;还认为要用二个字符串,感觉kmp还是没理解到位;又把kmp看了一下,看大神的思路,事实上这就是对next数组的一种应用;next数组事实上保存的就是字符串的相似度;保存的是其前一个字符的前缀和后缀相等的最大值,假如next[i]的值为6,那么它的前一个字符前缀和后缀最多就有6个相等。

字符的编号从0開始。这里面就能够推出一个规律;那么if(i%(i-next[i])==0),则i前面的串为一个轮回串,当中轮回子串出现i/(i-next[i])次。

以下是ac的代码。

#include <cstdio>
#include <cstring>
int n;
int next[1000001];
char s[1000001];
void get_next()//求出next数组
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<=n)
    {
        if(j==-1 || s[i]==s[j])
        {
            ++i;
            ++j;
            next[i]=j;
        }
        else
        j=next[j];
    }
}
int main()
{
    int t,j=1;
    while(scanf("%d",&n)&&n)
    {
       scanf("%s",s);
       get_next();
       printf("Test case #%d\n",j++);
       for(int i=2;i<=n;i++)
       {
           t=i-next[i]; //关键点在这里
           if(i%t==0&&i/t>1)
           {
               printf("%d %d\n",i,i/t);
           }
       }
       printf("\n");
    }
    return 0;
}
时间: 2024-08-14 07:56:05

hdu oj Period (kmp的应用)的相关文章

hdu 1358 period KMP入门

Period 题意:一个长为N (2 <= N <= 1 000 000) 的字符串,问前缀串长度为k(k > 1)是否是一个周期串,即k = A...A;若是则按k从小到大的顺序输出k即周期数: 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 题目其实是来自于LA的..挺好的一道题,用的是原版的kmp.. 写写对KMP

Hdu 1358 Period (KMP 求最小循环节)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1358 题目描述: 给出一个字符串S,输出S的前缀能表达成Ak的所有情况,每种情况输出前缀的结束位置和k. 解题思路: 打表算出next数组,然后对位置i求循环节,如果满足 i % (i - Next[i]) == 0 && Next[i] != 0,所对应的循环节(i - Next[i]), 循环次数是i / (i - Next[i]) 1 #include<cstdio> 2

HDU 1358 Period KMP

题意:求一个字符串的所有前缀是否是复制出来的. 解题思路:next 数值判断即可 解题代码: 1 // File Name: getnext.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月09日 星期二 22时35分02秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<dequ

poj1961 &amp; hdu 1358 Period(KMP)

poj 题目链接:http://poj.org/problem?id=1961 hdu题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1358 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

[C#] 逆袭——自制日刷千题的AC自动机攻克HDU OJ

前言 做过杭电.浙大或是北大等ACM题库的人一定对“刷题”不陌生,以杭电OJ为例:首先打开首页(http://acm.hdu.edu.cn/),然后登陆,接着找到“Online Exercise”下的“Problem Archive”,然后从众多题目中选择一个进行读题.构思.编程.然后提交.最后查看题解状态,如果AC了表示这一题被攻克了,否则就要重做了~一般情况下,“刷题”要求精神高度集中且经验丰富,否则很难成功AC,有时候甚至做一题要浪费半天的时间!(有时网速卡了,比抢火车票还要急!) 楼主在

HDU OJ 2159 FATE

#include <stdio.h> #include <string.h> int f[150][150] ; int w[150]; //»ñµÃ¾­Ñé int c[150]; //»¨·ÑµÄÈÌÄÍ¶È int main() { int n, m, kk, s; int i, j, k; int flag, cc; while(scanf("%d %d %d %d", &n, &m, &kk, &s )!=EOF) //

hdu 4644 BWT (kmp)

看完题目你很容易想到,这个题目的关键点就是如何把给出的数组还原成原数组. 还原的原数组之后不管是AC自动机 还是 kmp都可以解决 - -虽然我觉得kmp会超时的感觉. 那么如何还原这个字符串就是在个题目的难点... gc$aaac 1234567 排序之后变成了 $aaaccg 3456271 然后你按照排序后的下标依次走过去 会发现 $->a->c->a->a->c->g 3     5   2   4    6    7 也就恢复了原串. #include <

HDU 1618 Oulipo KMP题解

给出两个字符串,寻找一个字符串在另外一个字符串出现的频率. 原来kmp还有一个陷阱,下面注释出了,下标没步进好,就有一定几率出现超时的,也有一定几率出现错误,视具体的串而定. 修改一下就好了,kmp速度是很快的. #include <stdio.h> #include <string.h> const int MAX_TXT = 1000001; const int MAX_WORD = 10001; int gWlen, gTlen; char word[MAX_WORD]; i

LA3026 - Period(KMP)

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 the