字符串的最小表示法

欢迎参观!!==>原文链接 <== 欢迎参观!!
欢迎参观!!==> 博客地址 <== 欢迎参观!!
字符串的最小表示法,就是对于一个字符串,可以将它的最后一位放到第一位来,依次类推,一共有n种变形,n为字符串长度

例如:

s = “00ab”

变形有 : b00a, ab00, 0ab0

一共4种

那么找到其中字典序最小的一个,用的算法便是这个。

思路:

定义三个指针,i, j, k,初始i=0;j=1;k=0。

首先:

  • 如果 s[i] < s[j] 那么很明显 j++

  • 如果 s[i]>s[j] 那么也很明显 i = j++

  • 剩下的就是如果 s[i]==s[j] 的时候:

    这时候有一个性质就是在i和j之间的所有的字符一定是大于等于s[i]的

    另k=0,循环寻找第一个 s[i+k] != s[j+k] 的位置

    如果 s[i+k] < s[j+k] 那么 j += k+1

为什么呢?

​ 首先s[i]到s[i+k-1]一定是大于等于s[i],因为如果其中有一个数小于s[i],那么这个数一定在s[j]到s[j+k-1]中存在,又因为必定有一个会在后面,所以如果s[j]先碰到了,那么一定不会继续到k的位置的,所以一定不存在比s[i]小的字符。

​ 所以从其中的任意一个字符开始当作起始点,都不会比现在更小,所以只有从选出来的序列的后面那一个字符开始才有可能会是最小。

所以 j + = k+1

​ 如果序列中某个数和s[i]相等的话,那么一定会有之前或者以后再这个位置起始过,所以不需要再从这个位置进行起始。

​ 因为在这里i和j是等价的,i在前和j在前的结果是一样的,所以i和j的处理是相同的,下面就不仔细的进行讲解了,直接贴代码:

还有就是如果i==j那么让j++就可以回到原先的状态了

最后的时候,肯定是小的不会动,而大的会不停的向后移动,所以最后只需要输出i和j最小的一个即可

/**
 *字符串的最小表示法:
 *
 *循环同构
 *字符串S = “dcba”,它的循环同构"cbad",“badc”,“abcd”.
 *
 *最小表示
 *字符串和它的所有循环同构中字典序最小的字符串。S = “dcba"的最小表示"abcd”
 */
int minRepresent(char *s, int len) {
    int i = 0, j = 1, k = 0;
    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)  j = (j+k+1>i+1) ? j+k+1:i+1;
            else 		i = (i+k+1>j+1) ? i+k+1:j+1;
            k = 0;
        }
    }
    return (i<j) ? i:j;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值