最小表示法 最大表示法

最大最下表示法都一样。这里就说一个最小表示法吧!

 

最小表示法就是找出字符串S的的循环同构串中字典序最小的一个。

 

那么什么是循环同构串呢。是

--设S=bcad,且S’是S的循环同构的串。S’可以是bcad或者cadb,adbc,dbca

即在字符串S中从i>=0开始,从i循环到字符串末尾,再从头循环到i,所形成的字符就是S循环同构串。

 

因为这样的同构串不止一个,所以我们要找出其中字典序最小的一个(即字符串从小到大排序,其中最小的一个)

为什么要找出其中最小的一个呢?我也不知道诶

最小表示法其实就是找到位置i,从这个位置输出S,使得到的同构串字典序最小

朴素算法的思想就不仔细说了,因为是O(n^2)复杂度

 

实现方法:

(1).利用两个指针p1,p2。初始化时p1指向s[0],p2指向s[1]。

(2).k=0开始,检验s[p1+k]和s[p2+k]是否相等,相等则k++,一直下去,直到找到第一个不相同的字符(若k试了一个字符串的长度也没找到不同,即整个串都是相同的字符。则那个位置就是最小表示位置,算法终止并返回)。该过程中s[p1+k]和s[p2+k]的关系有三种:

  1).s[p1+k]>s[p2+k],p1滑动到p1+k+1处,s[p1--p1+k-1]不会是循环字符串的"最小表示"的前缀。

  2).s[p1+k]<s[p2+k],p2滑动到p2+k+1处。

  3).s[p1+k]==s[p2+k],则k++,if(k==len)返回结果。

  若滑动后p1==p2,将正在变化的那个指针在+1.直到p1,p2把整个字符串都检验完毕,返回两者中小于len的值。

(3).如果 k==len,则返回min( i , j )

  如果 p1>=len,返回 p2
  如果 p2>=len,返回p1当中最小的
}

//最小表示法
int get_minstring(char *s)
{
    int len = strlen(s);
    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+=k+1;
            else
                j+=k+1;
            if(i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}
 
//最大表示法
int get_maxstring(char *s)
{
    int len = strlen(s);
    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)
                j+=k+1;
            else
                i+=k+1;
            if(i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值