POJ 1509 Glass Beads 最小表示法

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/89636232

title

POJ 1509
Description

Once upon a time there was a famous actress. As you may expect, she played mostly Antique Comedies most of all. All the people loved her. But she was not interested in the crowds. Her big hobby were beads of any kind. Many bead makers were working for her and they manufactured new necklaces and bracelets every day. One day she called her main Inspector of Bead Makers (IBM) and told him she wanted a very long and special necklace.
The necklace should be made of glass beads of different sizes connected to each other but without any thread running through the beads, so that means the beads can be disconnected at any point. The actress chose the succession of beads she wants to have and the IBM promised to make the necklace. But then he realized a problem. The joint between two neighbouring beads is not very robust so it is possible that the necklace will get torn by its own weight. The situation becomes even worse when the necklace is disjoined. Moreover, the point of disconnection is very important. If there are small beads at the beginning, the possibility of tearing is much higher than if there were large beads. IBM wants to test the robustness of a necklace so he needs a program that will be able to determine the worst possible point of disjoining the beads.
The description of the necklace is a string A = a1a2 … am specifying sizes of the particular beads, where the last character am is considered to precede character a1 in circular fashion.
The disjoint point i is said to be worse than the disjoint point j if and only if the string aiai+1 … ana1 … ai-1 is lexicografically smaller than the string ajaj+1 … ana1 … aj-1. String a1a2 … an is lexicografically smaller than the string b1b2 … bn if and only if there exists an integer i, i <= n, so that aj=bj, for each j, 1 <= j < i and ai < bi

Input

The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case consists of exactly one line containing necklace description. Maximal length of each description is 10000 characters. Each bead is represented by a lower-case character of the english alphabet (a–z), where a < b … z.

Output

For each case, print exactly one line containing only one integer – number of the bead which is the first at the worst possible disjoining, i.e.\ such i, that the string A[i] is lexicographically smallest among all the n possible disjoinings of a necklace. If there are more than one solution, print the one with the lowest i.

Sample Input

4
helloworld
amandamanda
dontcallmebfu
aaabaaa

Sample Output

10
11
6
5

Source

Central Europe 1998

analysis

来自阿_波_

算法用法

最小表示法是我在看插头DP的时候看到的一个名词,就先来看了一下这个算法,还是蛮简单的,有一个首位相连的字符串,我们要寻找一个位置,从这个位置向后形成一个新字符串,我们需要使这个字符串字典序最小。

算法解释

我们这里要 i = 0 , j = 1 , k = 0 i = 0,j = 1,k = 0 ,表示从 i i 开始 k k 长度和从 j j 开始 k k 长度的字符串相同( i j i,j 表示当前判断的位置)。

当我们 s t r [ i ] = = s t r [ j ] str[i] == str[j] 时,根据上面 k k 的定义,我们的需要进行 k + 1 k+1 操作;

s t r [ i ] &gt; s t r [ j ] str[i] &gt; str[j] 时,我们发现 i i 位置比 j j 位置上字典序要大,那么不能使用 i i 作为开头了,我们要将 i i 向后移动,移动多少呢?有因为 i i 开头和 j j 开头的有 k k 个相同的字符,那么就执行 i = i + k + 1 i = i + k +1

相反 s t r [ i ] &lt; s t r [ j ] str[i] &lt; str[j] 时,执行: j = j + k + 1 j = j + k +1

最终 i i j j 中较小的值就是我们最终开始的位置。

相反如果是最大表示法的话,我们就要求解字典序最大的字符串,那么我们只需要在执行第二或第三个操作时选择较大的那个位置较好了。

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=11111;

template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

char s[maxn];
inline int getmin()
{
	int len=strlen(s);
	int i=0, j=1, k=0;//表示从i开始k长度和从j开始k长度的字符串相同
	while (i<len && j<len && k<len)
	{
		int t=s[(i+k)%len] - s[(j+k)%len];//t用来计算相对应位置上那个字典序较大
		if (!t) ++k;//字符相等的情况
		else
		{
			if (t>0) i+=k+1;//i位置大,最大表示法: j += k+1
			else j+=k+1;//j位置大,最大表示法: i += k+1
			if (i==j) ++j;
			k=0;
		}
	}
	return i<j?i:j;
}

int main()
{
	int n;read(n);
	for (int i=1; i<=n; ++i)
	{
		scanf("%s",s);
		printf("%d\n",getmin()+1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/89636232