zoukankan      html  css  js  c++  java
  • 【算法】字符串的最小表示法

    字符串的最小表示法,就是对于一个字符串,可以将它的最后一位放到第一位来,依次类推,一共有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最小的一个即可

    int getmin(char *s){
        int n=strlen(s);
        int i=0,j=1,k=0,t;
        while(i<n && j<n && k<n){
            t=s[(i+k)%n]-s[(j+k)%n];
            if (!t) k++;
            else{
                if (t>0) i+=k+1; 
                else j+=k+1;
                if (i==j) j++;
                k=0;
            }
        }
        return i<j?i:j;
    }
    View Code
  • 相关阅读:
    jwt原理
    图书管理系统后端
    图书管理系统前端
    图书管理前端页面
    Linux多任务: exec 和fork()的联用
    CPU 字长与存储器位宽不一致处理
    关键字volatule
    linux C 中断程序:利用队列保存中断类型
    Linux下的Make与Makefile
    C :assert() 的用法
  • 原文地址:https://www.cnblogs.com/XGHeaven/p/4009210.html
Copyright © 2011-2022 走看看