[xjoi1898] [hdu4333]Revolving Digits

/*注意注意:本题非hdu4333原题,而是简化版,原版有多组数据。但此代码在修改输入后依旧可以通过多组数据*/

给出一个数字串,问有多少本质不同同构串比原串小,一样,大.
同构串是指,对于原串S[1-N]通过旋转变成同构串S[i-N]+S[0-i-1].
本质不同,指的是字符串不一样.

输入格式:

一行一个数字串

输出格式:

一行,输出本质不同的同构串比原串小,一样,大的三个数,用一个空格分隔开。

样例输入:

123123

样例输出:

0 1 2

数据范围:

数字串长度<=100000

首先,我们用KMP求得KMP中的next数组nex,这有什么用呢?其功能在于求出原字符串的循环节个数,以此保证计数的字符串本质不同

然后,设原字符串为s2,字符串s1=s2+s2。以s1为母串,s2为子串跑EKMP。

最后,对于每一个ex[i],大于等于s2的长度即从第i个位置开始的组成的数与原数相等,否则只要比较s[i]与s[i+next[i]](EKMP的next)。

#include<cstdio>
#include<cstring>
using namespace std;
char s1[1000100],s2[1000100];
int ex[1000100],nxt[1000100],nex[1000100];
void get(char *s2){
    int m=strlen(s2);
    nex[0]=nex[1]=0;int j=0;
    for(int i=1;i<m;i++){
        while(j>0&&s2[i]!=s2[j])j=nex[j];
        if(s2[i]==s2[j])j++;
        nex[i+1]=j;
    }
}
void getex(char *s2){
    int j=0,n=strlen(s2);
    while(j+1<n&&s2[j+1]==s2[j])j++;
    nxt[0]=n;nxt[1]=j;int po=1,p=nxt[1]+1;
    for(int i=2;i<n;i++){
        int len=nxt[i-po];
        if(len+i<p)nxt[i]=len;
        else{
            int j=p-i;
            if(j<0)j=0;
            while(i+j<n&&s2[j]==s2[j+i])j++;
            nxt[i]=j;
            po=i;
            p=nxt[po]+po;
        }
    }
}
void exkmp(char *s1,char *s2){
    int j=0,n=strlen(s1),m=strlen(s2);
    while(s1[j]==s2[j]&&j<n&&j<m)j++;
    ex[0]=j;int po=0,p=ex[0];
    for(int i=1;i<n;i++){
        int len=nxt[i-po];
        if(len+i<p)ex[i]=len;
        else{
            int j=p-i;
            while(i+j<n&&j<m&&s1[j+i]==s2[j])j++;
            ex[i]=j;
            po=i;
            p=ex[po]+po;
        }
    }
}
int main(){
    scanf("%s",s2);int len=strlen(s2);
    for(int i=0;i<len;i++)
    s1[i]=s2[i],s1[i+len]=s2[i];
    getex(s2);
    exkmp(s1,s2);
    get(s2);

    int temp=len%(len-nex[len])==0?len/(len-nex[len]):1;
    int a=0,b=0,c=0;
    for(int i=0;i<len;i++){
        if(ex[i]>=len)b++;
        else if(s1[i+ex[i]]<s2[ex[i]])a++;
        else c++;
    }
    printf("%d %d %d",a/temp,b/temp,c/temp);
}
时间: 2024-10-08 21:26:42

[xjoi1898] [hdu4333]Revolving Digits的相关文章

hdu4333 Revolving Digits 扩展kmp

/** 参考:http://blog.csdn.net/acdreamers/article/details/8313828 参考:http://www.61mon.com/index.php/archives/186/ 题目:hdu4333 Revolving Digits 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意: 给定一个数字(不含前导0),它的最后一个数字放到最前面形成一个新的数字,然后对新的数字继续处理. 问有多少种不同的

hdu4333 Revolving Digits(扩展kmp+kmp最小循环节)

题目链接:点击打开链接 题意描述:给定一个字符串,可以把字符串的后x位移到字符串前面组成一个新的字符串?问对于所有的新组成的字符串中去掉重复的之后,比原串小的个数,等于的个数,大于的个数? 解题思路:扩展KMP(next1[i]数组含义:x[i···len-1]与x[0···len-1]的最长公共前缀) 分析:首先我们把字符串s复制一遍接到原字符串后面形成ss,这样在ss中以i(i>=0&&i<len)为起点的长度为len的字符串就是所有可能的新字符串: 讲到这里,问题转变为在

扩展KMP - HDU 4333 Revolving Digits

Revolving Digits Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=4333 Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. analyse: KMP的经典题. 首先我们将原串扩展成两倍,算一遍扩展KMP(自匹配),时间复杂度O(n). 这样一来,我们就得到了eKMP[i],eKMP[i]代表s[i...len-1]与s的最长

HDU 4333 Revolving Digits 扩展KMP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来相同,有多少比原来的小. 思路:拓展KMP中的next数组标记的是子串和母串的公共前缀的长度,要将字符串长度变成原来二倍,这样如果变换后不是完全相同的数字也即公共前缀长度大于等于字符串长度,那么字母串公共前缀的下一位的大小比较就是题目所要求的比较.由于相同的数字串只算一次,则只要统计比较第一个"循环节"

hdu 4333 Revolving Digits

Revolving Digits http://acm.hdu.edu.cn/showproblem.php?pid=4333 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description One day Silence is interested in revolving the digits of a positive integer. In th

字符串(扩展KMP):HDU 4333 Revolving Digits

Revolving Digits Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24729    Accepted Submission(s): 5381 Problem Description One day Silence is interested in revolving the digits of a positive int

扩展KMP,附上例题(HDU - 4333 Revolving Digits)

给出模板串S和串T,长度分别为Slen和Tlen,在线性时间内,对于每个S[i](0<=i<Slen),求出S[i..Slen-1]与T的 最长公共前缀长度,记为extend[i],extend[i]存放s[i]开始与T的最长公共前缀长度. 例子 a a a a a a a b b b a a a a a c extend 5 4 3 2 1 0 0 0 0 0 HDU - 4333 Revolving Digits Time Limit: 3000/1000 MS (Java/Others)

Revolving Digits(扩展Kmp+最小循环节)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 Revolving Digits Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28267    Accepted Submission(s): 6363 Problem Description One day Silence is

【HDOJ】4333 Revolving Digits

扩展KMP基础题目. 1 /* 4333 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11