HDU 3374(KMP+最小表示法)

题目链接: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);
    }

}

时间: 2024-08-27 14:02:30

HDU 3374(KMP+最小表示法)的相关文章

HDU 3374 (KMP 最小表示法)

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2442    Accepted Submission(s): 1029 Problem Description Give you a string with length N, you can generate N strings by left shift

hdu String Problem(最小表示法入门题)

hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> using namespace std; const int N = 10010; int n; char s[105]; map<

hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?

题意:给定一个由小写字母组成的长度为 n 的字符串,首尾相连,可以从任意一个字符开始,顺时针或逆时针取这个串(长度为 n),求一个字典序最大的字符串的开始字符位置和顺时针或逆时针.如果有多个字典序最大的字符串,优先选择开始位置靠前的,如果开始位置相同,优先选择顺时针. 这种字符串的问题,第一反应是后缀数组,为了达到首尾相连的目的,所以先复制了一个两倍长的该字符串,然后再将串倒置,也弄成两倍长度,得到顺逆时针的两倍长的串,并对这两个字符串分别做后缀数组,得到 sa 数组(该串字典序第几小的后缀的开

hdu3374 kmp+最小表示法

Give you a string with length N, you can generate N strings by left shifts. For example let consider the string "SKYLONG", we can generate seven strings: String Rank SKYLONG 1 KYLONGS 2 YLONGSK 3 LONGSKY 4 ONGSKYL 5 NGSKYLO 6 GSKYLON 7 and lexic

hdu 2609 字符串最小表示法 虽然不是很懂 还是先贴上来吧。/,。/

还需要再消化一下这个算法.. 今天没有时间了,, 六级过了 就有大把时间 快活啊!#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<set> using namespace std; int getmin(string s) { int n=s.size(); int i=0,j=1,k=0,t; while(i<n &&a

HDU 3374 最小/大表示法+KMP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题意:给定一个串s,该串有strlen(s)个循环同构串,要求输出字典序最小的同构串的下标,字典序最小的出现次数,最大的同构串的下标,字典中最大的出现次数. 思路:对于求循环同构的字典序最小可以用最小表示法求得,最大也是一样.然后设ds为字符串s+s.然后就可以用KMP求最小串在ds出现的次数和最大串出现的次数了. #define _CRT_SECURE_NO_DEPRECATE #inclu

String Problem hdu 3374 最小表示法加KMP的next数组

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1492    Accepted Submission(s): 662 Problem Description Give you a string with length N, you can generate N strings by left shifts.

hdu 3374 String Problem (kmp+最大最小表示法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题目大意:输出最大和最小的是从哪一位开始的,同时输出最小循环节的个数. 这里简单介绍对字符串最小表示的方法: (1)  利用两个指针p1, p2.初始化时p1指向s[0], p2指向s[1]. (2)  k = 0开始,检验s[p1+k] 与 s[p2+k] 对应的字符是否相等,如果相等则k++,一直下去,直到找到第一个不同,(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,

HDU 3374 String Problem (KMP+最大最小表示)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove 题目:输出最大最小表示是从哪一位开始,而且输出数量 http://acm.hdu.edu.cn/showproblem.php?pid=3374 数量好求,肯定是字符串的循环节,循环节可以直接通过KMP的Next数组得到.这个和yobobobo曾经研究过半天.. 对于最大最小表示法,就是将字符串不断旋转,得到字典序最大或者最小的.