poj 2046&&poj1961KMP 前缀数组

Power Strings

Time Limit: 3000 MS Memory Limit: 65536 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

[Submit] [Status] [Discuss]

Description

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3
题意:求解最多重复子串利用KMP的前缀数组  以p为模式串 next【i】的意思 为前个字符组成的子串为s  则s的前next【i】个字符与后next【i】个字符相等   注意 : len(p)-next【len(p))】==循环节的长度
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
int next[1000002];
char p[1000002];

void find(char p[])
{
    int m=strlen(p+1);
    next[1]=0;
    for(int k=0,q=2; q<=m; q++)
    {
        while(k>0&&p[k+1]!=p[q])
            k=next[k];
        if(p[k+1]==p[q])
            k++;
        next[q]=k;
    }
}

int main()
{

    while(~scanf("%s",p+1))
    {
        if(!strcmp(".",p+1))
        break;
        find(p);
        int len=strlen(p+1);
        int len1=len-next[len];
        printf("%d\n",len%len1?1:len/len1);
    }

}

Period

Time Limit: 3000 MS Memory Limit: 30000 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

[Submit] [Status] [Discuss]

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

题意: 定义字符串A,若A最多由n个相同字串s连接而成,则A=s^n,如"aaa" = "a"^3,"abab" = "ab"^2  "ababa" = "ababa"^1  给出一个字符串A,求该字符串的所有前缀中有多少个前缀SA= s^n(n>1) 输出符合条件的前缀长度及其对应的n          如aaa  前缀aa的长度为2,由2个‘a‘组成  前缀aaa的长度为3,由3个"a"组成
分析:KMP
  若某一长度L的前缀符合上诉条件,则
    1.next[L]!=0(next[L]=0时字串为原串,不符合条件)
	2.L%(L-next[L])==0(此时字串的长度为L/next[L])

 对于2:有str[0]....str[next[L]-1]=str[L-next[L]-1]...str[L-1]
        =》str[L-next[L]-1] = str[L-next[L]-1+L-next[L]-1] = str[2*(L-next[L]-1)];
		假设S = L-next[L]-1;则有str[0]=str[s]=str[2*s]=str[3*s]...str[k*s],对于所有i%s==0,均有s[i]=s[0]
		同理,str[1]=str[s+1]=str[2*s+1]....
		      str[j]=str[s+j]=str[2*s+j]....
	    综上,若L%S==0,则可得L为str[0]...str[s-1]的相同字串组成,
		总长度为L,其中字串长度SL = s-0+1=L-next[L],循环次数为L/SL
        故对于所有大于1的前缀,只要其符合上述条件,即为答案之一
#include "stdio.h"
int p[1000010],N;
char str[1000010];

void get_p(int n)
{
    int i,j=-1;
    p[0]=-1;
    for(i=1;i<n;i++)
    {
        while(j>-1 && str[i]!=str[j+1]) j=p[j];
        if(str[i] == str[j+1]) j++;
        p[i]=j;
    }
}

int main()
{
    int i,j,cas=1;
    while(scanf("%d",&N),N)
    {
        scanf("%s",str);
        get_p(N);
        printf("Test case #%d\n",cas++);
        for(i=1;i<N;i++)
        {
            if(p[i]!=-1 && (i+1)%(i-p[i])==0)
               printf("%d %d\n",i+1,(i+1)/(i-p[i]));
        }
        printf("\n");
    }
}

http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html  看一看


poj 2046&&poj1961KMP 前缀数组

时间: 2024-10-12 17:44:42

poj 2046&&poj1961KMP 前缀数组的相关文章

poj 2566Bound Found(前缀和,尺取法)

http://poj.org/problem?id=2566: 题意:找连续的串,求和绝对值与所给数字最接近的串. 思路:先求下标为1的到其他下的串的值,也就是前缀和:这样可以在O(1)的时间内求出各个串的和.比如S1(1,1),S3(1,3); 那么S3-S1就是S(2,3): 然后对上面所求的前缀和按从小到大排序.(因为取的是绝对值所以abs(Sn-Sk)==abs(Sk-Sn)); 这样就可以用尺取法去做了.复杂度为O(n); 还可以用二分取找值,复杂度为O(n*log(n)); 1 #i

POJ 2217 Secretary (后缀数组)

题目大意: 计算两个字符串的最长的公共字符串字串的长度. 思路分析: 将两个串合并起来. 然后直接跑后缀数组求出height 然后就可以直接扫描一次height ,加个是不是在一个串中的判断就可以了. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 200005 using namespace std; char str[ma

POJ 1226 Substrings (后缀数组)

题目大意: 问的是m个字符串里,都出现过的子串.子串也可以出现在这个串的逆序串中. 思路分析: 居然wa在全5个 "a" 的数据上. 二分的时候下界不能为0.. 思路大致上是把原串和逆序串全部处理出来,放入str中,然后在每个串中间加一个没有出现过的. 此处注意输入不仅仅是字母. 然后跑一遍后缀数组. 然后用标记计数就好了. #include <iostream> #include <cstdio> #include <algorithm> #inc

士兵杀敌5 前缀数组

士兵杀敌(五) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为0~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个人身上,这样,有时候,计算他们中的哪一个人到底有多少军功就是一个比较困难的事情. 在这样的情况下,南将军却经常会在许多次战役之后询问军师小工第i号士兵到第j号士兵所有人的总军功数. 请你帮助军师小工回答南将军的提问. 输入

HDOJ3336 Count the string 【KMP前缀数组】+【动态规划】

Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4212    Accepted Submission(s): 1962 Problem Description It is well known that AekdyCoin is good at string problems as well as n

poj 2299 树状数组求逆序数+离散化

http://poj.org/problem?id=2299 最初做离散化的时候没太确定但是写完发现对的---因为后缀数组学的时候,,这种思维习惯了吧 1.初始化as[i]=i:对as数组按照num[]的大小间接排序 2.bs[as[i]]=i:现在bs数组就是num[]数组的离散化后的结果 3.注意,树状数组中lowbit(i)  i是不可以为0的,0&(-0)=0,死循环... #include <cstdio> #include <cstring> #include

KMP字符串匹配算法及next前缀数组的应用

#KMP字符串匹配算法及next前缀数组的应用------ KMP算法通常是我们学习字符串匹配算法时遇见的第一个算法,另外还有Rabin-Karp, Sunday算法等. 相对于其他字符串匹配算法, kmp在字符串中字符重复率低的情况下并不具备优势,那为什么KMP算法会作为经典的教学算法呢? 原因可能是:KMP算法充分利用next前缀数组的信息来优化算法,减小时间复杂度的思路在很多字符串相关问题中能给我们启发. 首先上KMP字符串匹配算法, [leetcode在线测试地址](https://le

前缀数组

参考博客:KMP算法(kuangbin) 另讲得比较好的博客或网站:前缀函数与 KMP 算法 KMP算法(研究总结,字符串) const int maxn=1e5; int Next[maxn]; /*求前缀数组*/ /*t[0]对应的Next数组值为Next[1]*/ /*Next[0]=-1 方便判断是否都不能匹配*/ void getNext(string t) { int i=0,j=-1,n=t.length(); Next[0]=-1; while(i<n) { if(j==-1||

POJ-2752(KMP算法+前缀数组的应用)

Seek the Name, Seek the Fame POJ-2752 本题使用的算法还是KMP 最主要的片段就是前缀数组pi的理解,这里要求解的纸盒pi[n-1]有关,但是还是需要使用一个循环来依次找到前面符合的前缀(所谓符合就是可以保持既是前缀也是s的后缀的子串长度). #include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<set>