zoukankan      html  css  js  c++  java
  • 字符串最小表示法模板

    http://wenku.baidu.com/link?url=1hkGv3wY1CFD17E5RsyfFUCSPBmEJHfyaJZHLXIPnp1wHG54OyMGgLhVCwdt7YuEGENhnGyH7AJeC85giBGXrZg6dW6fdIU2-n7jQiLY9XG

    循环字符串的最小表示法的问题可以这样描述:

     

    对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。由于语言能力有限,还是用实际例子来解释比较容易:

     设S=bcad,且S’是S的循环同构的串。S’可以是bcad或者cadb,adbc,dbca。而且最小表示的S’是adbc。 对于字符串循环同构的最小表示法,其问题实质是求

    S串的一个位置,从这个位置开始循环输出S,得到的S’字典序最小。 一种朴素的方法是设计i,j两个指针。其中i指向最小表示的位置,j作为比较指针。 令i=0,j=1 

    如果S[i] > S[j] i=j, j=i+1 

    如果S[i] < S[j] j++

    如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]    

      如果S[i+k] > S[j+k] i=j,j=i+1 

      否则 j++ 

    返回i 

    起初,我想在j指针后移的过程中加入一个优化。就是j每次不是加1,而是移动到l位置。其中,l>j且S[l]<=S[j]。但是,即使加入这一优化,在遇到bbb…bbbbbba这样的字符串时

    复杂度将退化到O(n^2)。

    注意到,朴素算法的缺陷在于斜体的情况下i指针的移动太少了。针对这一问题改进就得到了最小表示法的算法。最小表示法的算法思路是维护两个指针i,j。

     令i=0,j=1 

    如果S[i] > S[j] i=j, j=i+1 

    如果S[i] < S[j] j++ 

    如果S[i]==S[j] 

      设指针k,分别从i和j位置向下比较,直到S[i] != S[j] 

      如果S[i+k] > S[j+k] i=i+k 

      否则j++ 

    返回i和j的小者

     

    注意到上面两个算法唯一的区别是粗体的一行。这一行就把复杂度降到O(n)了。

     

    值得一提的是,与KMP类似,最小表示法处理的是一个字符串S的性质,而不是看论文时给人感觉的处理两个字符串。 

    应用最小表示法判断两个字符串同构,只要将两个串的最小表示求出来,然后从最小表示开始比较。剩下的工作就不用多说了。  

    int get_min()   
    {    
        int i=0,j=1,k=0,t,l=strlen(s);
        while(i<l&&j<l&&k<l) 
        {             
            t=s[(j+k)%l]-s[(i+k)%l];          
            if(!t) 
                k++;           
            else
            {   
                if(t>0)
                    j=j+k+1;              
                else
                    i=i+k+1;                
                if(i==j)
                    j++;      
                k=0;      
            }   
        }      
        return (i<j?i:j);   
    } 
  • 相关阅读:
    SQL优化系列(三)- 用最少的索引获得最大的性能提升
    SQL优化系列(二)- 优化Top SQL
    SQL优化神器
    优化SQL之最快等价SQL
    ngnix反向代理导致请求头header中的信息丢失
    centos7安装docker
    (一)硬盘技术
    (四)存储行业基础知识
    (三)磁盘阵列技术
    硬盘的文件类型解释!
  • 原文地址:https://www.cnblogs.com/sweat123/p/4723265.html
Copyright © 2011-2022 走看看