最小(大)表示法

该篇博客介绍了如何使用三指针方法寻找首尾相连字符串的最小字典序(或最大字典序)表示,并提供了一个具体的题目实例,展示了如何结合map数据结构应用这一方法。代码实现中,通过不断比较字符串的不同部分,确定最小字典序串的起始位置,并统计不同旋转项链的种类。
摘要由CSDN通过智能技术生成

在首尾相连的字符串中,有一个最小(大)表示法的概念,意思就是在字符串旋转的过程中,有一种情况下字符串的字典序最小(大)。这里我们使用三指针的方法来寻找最小(大)的字典序串,首先破环成串,然后用i,j分别指定两个要比较的串的初始位置,k表示串比较的长度,若比较出两串的不同位置则将大的串的指针值前移,最终取i,j的最小值。

代码如下:

int getmin(string s,int len)//三指针搜索最小(大)序列 
{
	int i=0,j=1,k=0;
	while(i<len&&j<len)
	{
		k=0;
		while(s[i+k]==s[j+k]&&k<len)
			k++;
		if(s[i+k]<s[j+k])//求最大则是是s[i+k]>s[j+k] 
			j+=(k+1);
		else
			i+=(k+1); 
		//跳过已经比较的一段 
		if(i==j)//若出现i==j的情况则岔开一个继续比较 
			i++;
	}
	return min(i,j);//返回最小(大)字典序串的起点 
}

下面给出一道题,利用map与最小表示法即可

Problem - 2609

题解:

#include "cstdio"
#include "string"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"map"
#include"cmath"

using namespace std;
int getmin(string s,int len)//三指针搜索最小(大)序列 
{
	int i=0,j=1,k=0;
	while(i<len&&j<len)
	{
		k=0;
		while(s[i+k]==s[j+k]&&k<len)
			k++;
		if(s[i+k]<s[j+k])//求最大则是是s[i+k]>s[j+k] 
			j+=(k+1);
		else
			i+=(k+1); 
		//跳过已经比较的一段 
		if(i==j)//若出现i==j的情况则岔开一个继续比较 
			i++;
	}
	return min(i,j);//返回最小(大)字典序串的起点 
}
//可旋转项链
int main()
{
	int n; 
	while(scanf("%d",&n)!=EOF)
	{
		int ans=0;
		map<string,int>a;
		while(n--)
		{
			string s;
			cin>>s;
			int len=s.length();
			for(int i=0;i<len;i++)
				s+=s[i];
			//破环成串 
			int index=getmin(s,len);//得到最小字典序的字符串的起点 
			string ss=s.substr(index,len);
			if(a[ss]==0)
			{
				ans++;
				a[ss]=1;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会当凌绝顶丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值