码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3374(KMP+最小表示法)

时间:2015-07-19 16:17:44      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374

题意:给出字符串,求最小表示法和最大表示法,并输出有几次出现,其实就是最小循环节的个数

题解:最小表示法求解,KMP求解最小循环节 最小循环节 = len - Next[len]  个数必须整出,如不整除,则为1.

 

代码如下:

技术分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 2000000+50; //开两倍的原因是要复制串长 
char s1[maxn],s2[maxn];
int Next[maxn>>1];
int smallest(char *s) 
{
    int i = 0,j = 1,k = 0;
    int len = strlen(s);
    strcpy(s2,s);
    strcat(s,s2);
    while(i<len&&j<len)
    {
        k=0;
        while(k<len&&(s[i+k]==s[j+k]))
            k++;
        if(k>=len)
            break;
        if(s[i+k]>s[j+k])
            i=max(i+k+1,j+1);
        else
            j=max(i+1,j+k+1);
    }
    return min(i,j);
} 
int biggest(char *s) 
{
    int i = 0,j = 1,k = 0;
    int len = strlen(s);
    strcpy(s2,s);
    strcat(s,s2);
    while(i<len&&j<len)
    {
        k=0;
        while(k<len&&(s[i+k]==s[j+k]))
            k++;
        if(k>=len)
            break;
        if(s[i+k]<s[j+k])
            i=max(i+k+1,j+1);
        else
            j=max(i+1,j+k+1);
    }
    return min(i,j);
} 

void getNext(int len)
{
    int i=0,j=-1;
    Next[0]=-1;
    while(i<len)
    {
        if(j==-1||s1[i]==s1[j])
        i++,j++,Next[i]=j;
        else
        j=Next[j];
    }
}
int main()
{
    while(~scanf("%s",s1))
    {
        int len = strlen(s1);
        int k1 = smallest(s1);
        int k2 = biggest(s1);
        getNext(len);
        int sum = len - Next[len];
        if(len%sum==0)
        sum = len/sum;
        else
        sum=1;
        printf("%d %d %d %d\n",k1+1,sum,k2+1,sum);
    }
    
}
View Code

 

HDU 3374(KMP+最小表示法)

标签:

原文地址:http://www.cnblogs.com/ikids/p/4658641.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!