最小表示法--让你速度gank序列

    看到一个哈利油问我最小表示法,正好为了省赛我在整理算法,结果。。这个算法被我忘记怎么用了,果断复习了下。

    题:给你一个首尾相接的序列,即表示它可以循环位移形成新序列,要你找出满足某些规则的那个序列,比如字典序最小。

    比如: s[5]={3,2,5,1,4}求它字典序最小的那个由循环位移得到的序列,答案是{1,4,3,2,5};

    知道它是用来解决什么问题了,然后是代码,相信很多人对于看不懂就是陷在了纠结里面,然后,浩爷给你来解梦-。-!

    我觉得先把代码拿出来然后再仔细分析惑点好一些。

int ppp(int *s, int l)//最小表示法求字典序最小的序列
{//这里输入是s=string+string,l=strlen(string)*2
    int x=0,y=1,k=0;//初始化,从第二个开始比较
    while(x<l&&y<l)
    {
        k=0;
        while(s[x+k]==s[y+k]&&k<l) k++;//一直匹配到不相等
        if(k==l) return x;//如果把最后一个都匹配完了表示x开头的就是字典序最小的
        if(s[x+k]>s[y+k])//如果最后不相等的两个元素是x+k大一些
        {
            x=max(y+1,x+k+1);//那么x直接跳到“这个元素后面那个位置”和“y后面那个位置”的更大值
        }
        else//y+k的这个元素大一些
        {
            y=max(x+1,y+k+1);//同上
        }
    }
    if(x<l) return x;如果是正常结束while循环,x和y一定有一个是等于l的,所以返回小于l的那个就行了
    return y;
}

有不懂,我理解你的心情,比如为什么s[x+k]>s[y+k]的时候x跳向y+1和x+k+1之间的更大值?能确保跳过的这中间部分没有字典序最小的?

说实在的,别想太复杂了,不然陷进去了就难出来。下面上两个图来讲解纠结的地方。


下面这个,其实就是理解成循环节,把循环节当成一个值就能理解了


这个总结给力不给力?如果比较时x<y,那么就要记住x+1~y-1这些点开头的序列都是字典序比x开头大的,反之依然。

就像DP一样,我就抓紧某个状态,啃死了你这个状态的属性就是这样的,然后用它来推下一个。

很多人纠结的最多的点就在我这个总结的第2条里面,把这里看完你就知道为什么中间不会有更优这个问题了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值