• 字符串的最小表示法


    三个变量

    • i的含义是,第i个位置开始的字符串,
    • j的含义是,第j个位置开始的字符串,
    • k的含义是,从i个位置开始的字符串a,和从j个位置开始的字符串b,它们两个相同的长度。

    思路

    1. 如果 s[(i+k)%len]>s[(j+k)%len] ,也就是在比较了相同的k位之后,字符串a和b不相同了。此时的a的字典序比较大,说明字符串的最小表示的开始位置不是i,但是 i~ i+k的字符串却和 j~j+k的字符串是相等的,所以我们把i的位置设置为 k+1 的位置,让i重新选取开始位置和字符串j比较。

    2. 如果,s[(i+k)%len]<s[(j+k)%len],说明字符串a小于字符串b,此时字符串b可以被舍弃,重新开始选取b,位置选取哪里?
      我们选一个例子,13134,最开始i=0,j=1,k=0,第一步之后,j=2。因为只有s[(j+k)%len]>s[(i+k)%len]的时候,j才会增加。

    3. 所以当a串等于b串的时候,在此之前,a[i+1] ~ a[i+k]>a[i],而因为b==a,所以,b[j+1] ~ b[j+k] >b[0] (b[0]==a[0]) 。所以,我们选取位置的时候,没有必要考虑 j~j+k位置的字符,我们直接将j移到k+1的位置。
      用例子做说明的话,字符串 13 和字符串13 ,此时比较下一位 1 和 4,因为ab的前几位均相同,我们没有必要再让j从下一位开始,一位一位和i=0开始的字符串去比较。

    注意

    代码里给了两组样例,这里需要说明的是,字符串的最小表示法表示的仅仅是,相对于传入字串,哪个位置开始为最小字串。
    设最小表示位置为 k ,对于原字符串 s ,从 k 开始循环则 s 最小,但是对于 0<k<len_s-1 , 这样对于从k开始的substr中,字符串最小表示的位置需要重新查找。
    比如 字符串 101010 最小表示位置是1,但是截开之后,字符串01010 ,它的最小表示位置在最后一位。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    int getmin(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) {
                    i=i+k+1;
                }
                else {
                    j=j+k+1;
                }
                if (i==j) {
                    j++;
                }
                k=0;
            }
        }
        return i<j?i:j;
    }
    
    int main()
    {
        char str[200];
        scanf("%s",str);
        int len=strlen(str);
        printf("%d
    ",getmin(str,len));
        return 0;
    }
     /*
    2213211
    101010
    */
    
    
  • 相关阅读:
    【学习笔记】查看CUDA版本
    如果Visual Studio太大,不妨还是用VSCode开发C#项目吧
    Visual Studio npm配置淘宝镜像
    c++读写锁--读者写者问题
    c++内存对象模型--vs2017下的分析,32位
    android作业
    android连接数据库
    android第十周(增删改查)
    android-购物车
    android计算器
  • 原文地址:https://www.cnblogs.com/xyqxyq/p/12328889.html
Copyright © 2020-2023  润新知