HDU 4162 Shape Number (最小表示法)

题意:给你一串n个数,求出循环来看一阶差的最小字典序:数字串看成一个顺时针的环,从某一点开始顺时针循环整个环,保证字典序最小就是答案

例如给你 2 1 3 就会得到(1-2+8 注意题意负数需要加8) (3-1) (2-3+8)-> 7 2 7 答案就是2 7 7。

典型的最小表示法。线性时间内求出最小字典序。

首先复制一遍数字串在原串后面,这样从原串任意位置开始向再后n个位置就是答案。接着双指针维护,直接双指针暴力比较数字串,当出现不同数字时,就把字典序大的那个指针向后移动尽量多的位置这样可以保证无回溯比较

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=600010;
string str;
int MinRpst(int len)//最小表示法
{
    int i=0,j=1,k;
    while(i<len&&j<len)
    {
        k=0;
        while(k<len&&str[i+k]==str[j+k])//暴力寻找
            ++k;
        if(k==len)//结束
            return min(i,j);
        if(str[i+k]>str[j+k])//双指针处理无回溯的最小表示法(修改就是最大表示法)
        {
            if(i+k+1>j)//保证移动最大就会无回溯
                i=i+k+1;
            else
                i=j+1;
        }
        else
        {
            if(j+k+1>i)
                j=j+k+1;
            else
                j=i+1;
        }
    }
    return min(i,j);
}
int main()
{
    string tem;
    while(cin >> str)
    {

        tem.clear();
        int len=str.size();
            tem=str[0]-str[len-1]<0?str[0]-str[len-1]+8+‘0‘:str[0]-str[len-1]+‘0‘;//最后一个字符

        for(int i=0;i<len-1;++i)//一阶差
        str[i]=str[i+1]-str[i]<0?str[i+1]-str[i]+8+‘0‘:str[i+1]-str[i]+‘0‘;

        str.erase(len-1);//删除
        str+=tem;//添加
        str+=str;//复制一次在后面(处理环的经典方式)

        int sta=MinRpst(len);

        for(int i=sta;i<sta+len;++i)
        cout << str[i];
        cout << endl;
    }
    return 0;
}
时间: 2024-10-14 16:07:52

HDU 4162 Shape Number (最小表示法)的相关文章

HDU 4162 Shape Number 最小表示法

Shape Number Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 981    Accepted Submission(s): 471 Problem Description In computer vision, a chain code is a sequence of numbers representing direc

HDU 4162 Shape Number(字符串,最小表示法)

HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[i] = (s[i] - s[i+1] + 8) % 8; 第二步是求出最小字典序的循环同构差分码,我之前没注意到字符串规模..直接用set做,MLE+TLE... 正确的方式应该是一种O(n)的解法,即最小表示法.//关于最小表示法的证明与详述请参考最小表示法:) 最小表示法算法: 初始时,i=0,j=

HDU 4162 Shape Number

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4162 题意: 求给定字符的一阶差分链的最小表示. 题解: 先求一阶差分链,再求一阶差分链的最小表示法. 代码: #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 3e5 + 10; char s1[maxn],s2[maxn]; int s

Shape Number (最小表示法)

题目链接 一个字符串,这个字符串的首尾是连在一起的,要求寻找一个位置,以该位置为起点的字符串的字典序在所有的字符串中中最小. 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline ll read(){ 5 int x = 0, f = 1; char ch = getchar(); 6 while(ch > '9' || ch < '0'){if (ch == '-')

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

HDU 3374(KMP+最小表示法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题意:给出字符串,求最小表示法和最大表示法,并输出有几次出现,其实就是最小循环节的个数 题解:最小表示法求解,KMP求解最小循环节 最小循环节 = len - Next[len]  个数必须整出,如不整除,则为1. 代码如下: #include<iostream> #include<cstdio> #include<algorithm> #include<cst

hdu 2609 How many (最小表示法)

题意 给 \(n\) 个循环串,求本质不同串的数量 传送门 思路 最小表示法求下标,从最小下标处作为串的起点,将新串放到map中去重,最终map中的元素数量即为最终答案. 最小/大表示法 Code #include <cstdio> #include <cstring> #include <map> #include <string> using namespace std; const int maxn = 1e6+10; int n, l; char s

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<

HDU 4162 最小表示法

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4162 题意:给定一个只有0-7数字组成的串.现在要由原串构造出一个新串,新串的构造方法:相邻2个位置的数字的差值.若为负数则要加上8,问新构造出来的串的一个字典序最小同构串是什么? 思路:就按照题意构造出新串后,然后就是最小表示法了. #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstdio> #include&