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=1,分别以i,j,为起始点顺着i,j,往下比较直到找的str[i+k]!=str[j+k],然后分两种情况考虑:

1、  str[i+k]>str[j+k],i变成i=i+k+1,j不变,然后继续往下比较。

2、  str[i+k]<str[j+k],j变成j=j+k+1,i不变,然后继续往下比较。

直到i或j大于串长,找较小者。

最小表示法的实现代码是这样的:

/*s表示字符串,l表示字符串长度,输出最小字符串起始位置*/
int MinimumRepresentation(char *s, int l)
{
    int i = 0, j = 1, k = 0, t;
    while(i < l && j < l && k < l) {
        t = s[(i + k) >= l ? i + k - l : i + k] - s[(j + k) >= l ? j + k - l : j + k];
        if(!t) k++;
        else{
            if(t > 0) i = i + k + 1;
            else j = j + k + 1;
            if(i == j) ++ j;
            k = 0;
        }
    }
    return (i < j ? i : j);
}

AC code:(这次代码写的太丑啦。。)

/*
* @author Novicer
* language : C++/C
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

string s;
set<string>ss;

int main(){
//	freopen("input.txt","r",stdin);
	while(cin >> s)	{
//		cout << s << endl;
		ss.clear();
		int len = s.length();
		char tmp = s[0];
		set<string>:: iterator it;
		for(int i = 0 ; i < len - 1; i++){
			if(s[i] > s[i+1])
				s[i] = 8 - (s[i] - s[i+1]) + '0';
			else s[i] = s[i+1] - s[i] + '0';
//			cout << s[i] << ' ';
		}
		s[len-1] = (s[len-1]>tmp)? (8 - s[len-1] + tmp + '0') : (tmp - s[len-1] + '0');
//		cout << s << endl;
		int i = 0 , j = 1 , k = 0 , t;
		while(i < len && j < len && k < len){
			t = s[(i+k)] - s[(j+k)];
			if(t == 0) k++;
			else if(t > 0)	i += k + 1;
			else if(t < 0)	j += k + 1;
			if(t) k = 0;
			if(i == j) j++;
		}
		int pos = min(i,j);
//		cout << pos << endl;
		for(int i = 0 ; i < len ; i++)
			putchar(s[(i+pos) % len]);
		cout << endl;

//		cout << s << endl;

		s.clear();
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-22 19:56:41

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

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

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

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

[coj 1353 Guessing the Number]kmp,字符串最小表示法

题意:给一个字符串,求它的最小子串,使得原串是通过它重复得到的字符串的一个子串. 思路:先求最小长度,最小循环长度可以利用kmp的next数组快速得到,求出长度后然后利用字符串最小表示法求循环节的最小表示即可. #pragma comment(linker, "/STACK:10240000") #include <map> #include <set> #include <cmath> #include <ctime> #include

没有来源的题(似乎是什么POI?) 字符串——最小表示法

[题目描述]? 给你两个长度为 \(n\) 的字符串,问能否通过将某一字符串的一个前缀接到该串的后面使得两个字符串相等.若可以,你还可能被要求输出通过上述操作所能得到的字典序最小的字符串. [输入格式] ? ? 第一行两个整数 \(n,T\). ? 接下来两行,每行一个长度为 \(n\) 的字符串. [输出格式] ? 若可以,输出 \(TAK\),否则输出 \(NIE\).如果 \(T=1\),你还需要在下一行输出字典序最小的字符串. [数据范围] \(n \le 1000000\) 首先,什么

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2609 题意:给你n个字符串每个字符串可以左右移动但还是同一串比如 0110 可以表示为 0110 -> 1100 -> 1001 -> 0011->0110 这些都属于同一个字符串,最后问这n个字符串里一共有多少不同的字符串 可以将这些字符串都以其最小表示方法存下来复杂度为O(n)然后在sort一遍找一下有几个不同的就行了. #include <iostream> #inc

【转载】字符串最小表示法-O(n)算法

原博客链接:http://blog.csdn.net/zy691357966/article/details/39854359 未授权,侵权删. 因为这篇博客写得真好..转载了.. 红色的字是原博主写的,蓝色的字是我加的. ------------------------------------------------------------------------------------------------------------------------------------------

字符串最小表示法模版

1 //O(n) 2 char s[N],ss[N*2]; 3 int n=strlen(s+1); 4 for(int i=1;i<=n;i++) 5 ss[i+n]=s[i]; 6 int i=1,j=2,k; 7 while(i<=n && j<=n){ 8 for(k=0;k<n && s[i+k] == s[j+k]; k++); 9 if(k==n) break; 10 if(s[i+k]>s[j+k]){ 11 i=i+k+1;