POJ 1961 Period || HDU 1358 Period || ZOJ 2177 Period

/*
给定一个长度为n的字符串s,求它的每个前缀的 最短循环节。换句话说,对于每个i (2<=i<=n),
求一个最大的整数K>1 (如果K存在),使得S的前i个字符组成的前缀是某个字符串重复K次得到
的。输出所有存在K的i和对应的K。 

比如对于字符串aabaabaabaab, 只有当i=2,6,9,12时K存在,且分别为2,2,3,4 

 

用的 是很不常见的 MP 算法(其实就是个状态转移图的构造)

*/

Problem : 1358 ( Period )     Judge Status : Accepted
RunId : 7623334    Language : C++    Author : CherryChou
Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>


using namespace std;

const int MAXN=1000015;

char T[MAXN];
int F[MAXN]; 


void getfail(char *P,int *f)// MP算法
{
     f[0]=f[1]=0;
     int m=strlen(P);
     for(int i=1;i<m;i++){
       int j=f[i];
       while(j&&P[i]!=P[j]) j=f[j];
       f[i+1]=(P[i]==P[j]?j+1:0);
     }
}


int main(){
    int len,cnt=0;
    while(~scanf("%d%*c",&len),len){
      printf("Test case #%d\n",++cnt);
      scanf("%s",T);
      getfail(T,F);
      for(int i=2;i<=len;i++){
        if(F[i]>0&&i%(i-F[i])==0){
          printf("%d %d\n",i,i/(i-F[i]));
          }
      }
      puts("");
    }
    return 0;
}

 

Source Code

Problem: 1961 User: imutzcy
Memory: 5028K Time: 188MS
Language: C++ Result: Accepted
  • Source Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1000000 + 10;
    
    char str[maxn];
    int next[maxn];
    int n;
    
    void get_next()
    {
    	int j,k;
    	j=0;k=-1;next[0]=-1;
    	while(str[j]!='\0')
    	{
    		if(k==-1||str[j]==str[k])
    		{
    			j++;
    			k++;
    			if(j%(j-k)==0&&j/(j-k)>1)
    			  printf("%d %d\n",j,j/(j-k));
    			next[j]=k;
    		}
    		else k=next[k];
    	}
    }
    
    int main()
    {
    	int text=0;
    	while(~scanf("%d",&n),n)
    	{
    		scanf("%s",str);
    		printf("Test case #%d\n",++text);
    		get_next();
    		printf("\n");
    	}
    	return 0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值