最小表示法(模板)

问题:某字符串循环同构的所有字符串中,字典序最小的串是哪个?

1)什么是循环同构串?

例如 "a b c d f e" 字符串长度为 6, 那么就是说有 6 种循环同构的方法

"a b c d f e"  , " b c d f e a " ,  "c d f e a b" ,  "d f e a b c" ,  " f e a b c d" ,  "e a b c d f"

暴力解法:将所有的串都列出,然后排序。

O(N) 解法 : 最小表示法

算法思想:

  1. 定义 i  , j , k 三个指针 , i = 0, j = 1, k = 0 //  i、j是两个“ 怀疑是最小的位置 “ k 的作用是s[ i ] == s[ j ] 时 向后比较 s[ i + k ] 和 s[ j + k ] 的大小。
  2. 如果 s [ i ] < s [ j ]  那么  //  ++j , j指针向后移
  3. 如果 s [ i ] > s [ j ] 那么  //  i = j ++ , i 指针指向 j 的位置, j 向后移动
  4. 如果 s [ i ] == s [ j ] 那么我们就需要移动 k 指针,找出 s [ i + k ] !=  s [ j + k ] 的位置,(肯定谁小要谁)// 首先s[i]到s[i+k-1]一定是大于等于s[i],因为如果其中有一个数小于s[i],那么这个数一定在s[j]到s[j+k-1]中存在,又因为必定有一个会在后面,所以如果s[j]先碰到了,那么一定不会继续到k的位置的,所以一定不存在比s[i]小的字符
    1. s [ i + k ] == s [ j + k ] 那么  ++k
    2. s [ i + k ] > s [ j + k ] 那么 i += k + 1, 并把 k 归为 0
    3. s [ i + k ] < s [ j + k] 那么  j += k + 1,并把 k 归为 0
  5.  i == j  时,让 j 后移一位 ++j即可

最后(i 和 j)肯定是 小的不会动,而大的会不停向后移动,我们最后只用找出 i  和 j 中最小的那个即可。

模板:

string s;
int Get_Min(){
	int i = 0, j = 1, k = 0;
	int len = s.length();
	while(i < len && j < len && k < len){
		int t = s[(i + k) % len] - s[(j + k) % len];
		if(t == 0) ++k;
		else if(t < 0){	//s[(i + k)] < s[(j + k)]
			j += k + 1;
			k = 0;
		} else {	// s[(i + k)] > s[(j + k)]
			i += k + 1;
			k = 0;
		}
		if( i == j ) ++j;
	}
	return i < j ? i : j;
}

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值