最小表示法--让你速度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     {
        k=0;
        while(s[x+k]==s[y+k]&&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     return y;
}

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

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

最小表示法--让你速度gank序列_第1张图片

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

最小表示法--让你速度gank序列_第2张图片

这个总结给力不给力?如果比较时x

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

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

你可能感兴趣的:(望昨天-我还是一个小学生)