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
directions when following the contour of an object. For example, the
following figure shows the contour represented by the chain code
22234446466001207560 (starting at the upper-left corner).

Two
chain codes may represent the same shape if the shape has been rotated,
or if a different starting point is chosen for the contour. To
normalize the code for rotation, we can compute the first difference of
the chain code instead. The first difference is obtained by counting the
number of direction changes in counterclockwise direction between
consecutive elements in the chain code (the last element is consecutive
with the first one). In the above code, the first difference is

00110026202011676122
Finally,
to normalize for the starting point, we consider all cyclic rotations
of the first difference and choose among them the lexicographically
smallest such code. The resulting code is called the shape number.
00110026202011676122
01100262020116761220
11002620201167612200
...
20011002620201167612
In this case, 00110026202011676122 is the shape number of the shape above.

Input

The
input consists of a number of cases. The input of each case is given in
one line, consisting of a chain code of a shape. The length of the
chain code is at most 300,000, and all digits in the code are between 0
and 7 inclusive. The contour may intersect itself and needs not trace
back to the starting point.

Output

For each case, print the resulting shape number after the normalizations discussed above are performed.

Sample Input

22234446466001207560
12075602223444646600

Sample Output

00110026202011676122
00110026202011676122

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 300005
const int inf=0x7fffffff;   //无限大
string s;
char b[maxn];

int getminsub(char *a)
{
    int i=0,j=1,len=strlen(a),k=0; //取两个同构的字符串一个从下标0开始,一个从下标1开始
    while(i<len&&j<len&&k<len) //这里并没有将字符串复制一份添加到后面
    {
        if(k==len) break; //说明找到了a的最小表示
        if(i==j) j++;
        int ni=i+k,nj = j+k;
        if(ni>=len) ni-=len; //就是回到字符串的开始去
        if(nj>=len) nj-=len;
        if(a[ni]>a[nj])
        {
            i+=k+1;
            k=0;
        }
        else if(a[ni]<a[nj])
        {
            j+=k+1;
            k=0;
        }
        else k++;
    }
    return  i; //返回从第i个字符开始时a的最小表示
}

int main()
{
    while(cin>>s)
    {
        int n=s.size();
        for(int i=0;i<s.size();i++)
        {
            if(s[(i+1)%n]>=s[i])
                b[i]=(s[(i+1)%n]-s[i])+‘0‘;
            else
                b[i]=s[(i+1)%n]+8-s[i]+‘0‘;
        }

        int k=getminsub(b);
        for(int i=k;i<s.size()+k;i++)
        {
            cout<<b[i%n];
        }
        cout<<endl;
    }
}
时间: 2024-11-03 01:36:00

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

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 (最小表示法)

题意:给你一串n个数,求出循环来看一阶差的最小字典序:数字串看成一个顺时针的环,从某一点开始顺时针循环整个环,保证字典序最小就是答案 例如给你 2 1 3 就会得到(1-2+8 注意题意负数需要加8) (3-1) (2-3+8)-> 7 2 7 答案就是2 7 7. 典型的最小表示法.线性时间内求出最小字典序. 首先复制一遍数字串在原串后面,这样从原串任意位置开始向再后n个位置就是答案.接着双指针维护,直接双指针暴力比较数字串,当出现不同数字时,就把字典序大的那个指针向后移动尽量多的位置这样可以

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&