最小表示法汇总

1.题目链接:https://vjudge.net/contest/365138#problem/B
解法一:直接暴力利用string的compare和substr
(这样竟然也能过,哭了)

#include<iostream>
#include<cstdio>
#include<string>
using namespace  std;
int main()
{
	int t;
	cin>>t;
	string s;
	while(t--)
	{
		cin>>s;
		int len=s.size();
		s+=s;
		string mins=s.substr(0,len);
		int minpos=0;
		for(int i=1;i<len;i++)
		{
			string temp=s.substr(i,len);
			if(temp.compare(mins)<0)
			{
				mins=temp;
				minpos=i;
			}
		}
		printf("%d\n",minpos+1);
	}
	return 0;
}

解法二:最小表示法
用于求一个字符串首尾相连时的最小字典序
模版:

i=0,j=1;
while(i<=n&&j<=n) {
        for(k=0;k<n&&w[i+k]==w[j+k];k++);
        if(k==n) break;
        if(w[i+k]>w[j+k]) {
            i+=k+1; if(i==j) i++;
        }else {
            j+=k+1; if(i==j) j++;
        }
    }
    i=min(i,j);

意思就是从i=0、j=1开始,k=0
①如果s[i+k]s[j+k],则k++;
②如果s[i+k]>s[j+k],则i=i+k+1;若i
j,则i++;
③如果s[i+k]<s[j+k],则j=j+k+1,若i==j,则j++;
先来解释一下②,abcdabcae字符串为例,
i=0,j=4,k=0开始,当k=0,1,2时,s[i+k]==s[j+k],当k=3时,s[i+k]=‘d’,s[j+k]=‘a’,s[i+k]>s[j+k],此时要让i=i+k+1。那我们直接证明在i到i+k之间不存在最小字典序的字符串就好,取中间一点为i+p,因为s[i+k]>s[j+k],s[i+p]到s[i+k-1]与s[j+p]到s[j+k-1]相同,那么i+p到i+k字典序一定是大于j+p到j+k的,所以可以直接让i跳到i+k+1处。
③的证明也同理。

#include<iostream>
#include<cstdio>
#include<string>
using namespace  std;
int main()
{
	int t;
	cin>>t;
	string s;
	while(t--)
	{
		cin>>s;
		int len=s.size();
		s+=s;
		int i=0,j=1,k=0;
		while(i<len&&j<len)
		{
			k=0;
			while(k<len&&s[i+k]==s[j+k]) k++;
			if(k==len)
				break;
			if(s[i+k]>s[j+k])
			{
				i=i+k+1;
				if(i==j)
					i++;
			}
			else
			{
				j=j+k+1;
				if(i==j)
					j++;
			}
		}
		cout<<min(i,j)+1<<endl;
	}
	return 0;
}

2.HDU4162http://acm.hdu.edu.cn/showproblem.php?pid=4162
难在题意理解,就是为了便于记录一个图形的旋转等操作,将字符串表示成差分形式,及s[i]=(s[i+1]-s[i]+8)%8,然后利用最小表示法找最小字典序即可

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
string s;
int change[610000];
int len;
int MinimumRepresentation()
{
	int i=0,j=1;
	int k;
	while(i<len&&j<len)
	{
		k=0;
		while(k<len&&change[i+k]==change[j+k]) k++;
		if(k==len)
			break;
		if(change[i+k]>change[j+k])
		{
			i=i+k+1;
			if(i==j)
				i++;
		}
		else
		{
			j=j+k+1;
			if(i==j)
				j++;
		}
	}
	return min(i,j);
}
int main()
{
	while(cin>>s)
	{
		len=s.size();
		s+=s;
		for(int i=0;i<2*len-1;i++)
		{
			change[i]=(s[i+1]-s[i]+8)%8;
		}
		change[2*len-1]=change[len-1];
		int pos=MinimumRepresentation();
		for(int i=0;i<len;i++)
			printf("%d",change[i+pos]);
		printf("\n");
	}
	return 0;
}


原创文章 65 获赞 3 访问量 2096

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/105223681
今日推荐