原博客链接:http://blog.csdn.net/zy691357966/article/details/39854359

未授权,侵权删。

因为这篇博客写得真好。。转载了。。

红色的字是原博主写的,蓝色的字是我加的。

---------------------------------------------------------------------------------------------------------------------------------------------------------

这篇文章里的p1就是i,p2就是j

网上看了这篇文章后还是感觉有些地方讲的没有详细的证明所以添加了一点 红色字是博主写的

求字符串的循环最小表示:

上面说的两个字符串同构的,并没有直接先求出Min(s),而是通过指针移动,当某次匹配串长时,那个位置就是Min(s)。而这里的问题就是:不是给定两个串,而是给出一个串,求它的Min(s),eg:Min(“babba”) = 4。那么由于这里并非要求两个串的同构,而是直接求它的最小表示,由于源串和目标串相同,所以处理起来既容易又需要有一些变化:我们仍然设置两个指针,i, j,其中i指向0,j指向1,仍然采用上面的滑动方式:

(1)  利用两个指针i, j。初始化时i指向0, j指向1。

(2)  k = 0开始,检验s[i+k] 与 s[j+k] 对应的字符是否相等,如果相等则k++,一直下去,直到找到第一个不同,(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,算法终止并返回)。则该过程中,s[i+k] 与 s[j+k]的大小关系,有三种情况:

证明的时候假设(i<j)的,无伤大雅 ;

(A). s[i+k] > s[j+k],则i滑动到i+k+1处 --- 即s1[i->i+k]不会是该循环字符串的“最小表示”的前缀。

证明如下

(B). s[i+k] < s[j+k],则j滑动到j+k+1处,原因同上。

证明如下

(C). s[i+k] = s[j+k],则 k++; if (k == len) 返回结果。

注:这里滑动方式有个小细节,若滑动后i == j,将正在变化的那个指针再+1。直到p1、p2把整个字符串都检验完毕,返回两者中小于len 的值。(这里的字符串是从0开始的,所以末位是len-1)

(3)   如果 k == len, 则返回i与j中的最小值

如果 i >= len   则返回j(从1开始 : i>=len+1)

如果 j >= len   则返回i (从1开始: j>=len+1)

如果看了上一篇文章 很容易对这里的i,j 产生误会  误以为i为ans,j为比较指针

实际上这题中 i,j 都可能存有ans 两者互相更新,直到有一个更新后超过了len(包括len) 的时候 另一个即为正解

(4)   进一步的优化,例如:i要移到i+k+1时,如果i+k+1 <= p2的话,可以直接把i移到 j+1,因为,j到j+k已经检验过了该前缀比以i到i+k之间任何一个位前缀都小;j时的类似,移动到i+1。

这个优化就无需解释了

如i移到i+k+1,且i+k+1<=j,则j在i的后面,设j前一次位置为j',每一次跳的时候都保证了j'~j-1这一段任意一个字符开始的子串都不可能,又因为j本来等于i+1,就是i+1到j-1这一段都不可能,所以现在可以直接跳了。

至此,求一个字符串的循环最小表示在O(n)时间实现,感谢大牛的论文。其中实现时的小细节“如果滑动后p1 == p2,将正在变化的那个指针再+1”,开始没有考虑,害得我想了几个小时都觉得无法进行正确的移动。具体例题有两个:http://acm.zju.edu.cn 的2006和1729题。一个是10000规模一个是100000规模。运行时间前者是0S,后者是0.05S。

 
 
上自己丑陋的代码
 int MinimumRepresentation(int *s, int l)
{
int i,j,k;
i=;j=;k=;
while(i<l&&j<l)
{
k=;
while(s[i+k]==s[j+k]&&k<l) k++;
if(k==l) return i;
if(s[i+k]>s[j+k])
if(i+k+>j) i=i+k+;
else i=j+;
else if(j+k+>i) j=j+k+;
else j=i+;
}
if(i<l) return i;
else return j;
}
 

我也附上我的代码:

 int Min()
{
int i=,j=,k;
while(i<=sl && j<=sl)
{
k=;//debug 每次清零!
while(s[i+k]==s[j+k] && k<sl)//debug
{
k++;
if(k==sl) return minn(i,j);
}
if(s[i+k]>s[j+k])
{
if(i+k+<=j) i=j+;
else i=i+k+;
}
else
{
if(j+k+<=i) j=i+;
else j=j+k+;
} }
if(i<=sl) return i;
if(j<=sl) return j;
} int Max()
{
int i=,j=,k;
while(i<=sl && j<=sl)
{
k=;
while(s[i+k]==s[j+k] && k<sl)//debug k<sl
{
k++;
if(k==sl) return minn(i,j);
}
if(s[i+k]<s[j+k])
{
if(i+k+<=j) i=j+;
else i=i+k+;
}
else
{
if(j+k+<=i) j=i+;
else j=j+k+;
}
}
if(i<=sl) return i;
if(j<=sl) return j;
}

【转载】字符串最小表示法-O(n)算法的更多相关文章

  1. 牛客练习赛36 A Rabbit的字符串(字符串最小表示法)

    链接:https://ac.nowcoder.com/acm/contest/328/A来源:牛客网 题目描述 Rabbit得到了一个字符串,她的好朋友xxx可以给这个字符串施加一次魔法. 魔法可以选 ...

  2. bzoj2176 Strange string(字符串最小表示法)

    Time Limit: 10 Sec  Memory Limit: 259 MB 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的 ...

  3. [coj 1353 Guessing the Number]kmp,字符串最小表示法

    题意:给一个字符串,求它的最小子串,使得原串是通过它重复得到的字符串的一个子串. 思路:先求最小长度,最小循环长度可以利用kmp的next数组快速得到,求出长度后然后利用字符串最小表示法求循环节的最小 ...

  4. BZOJ1398: Vijos1382寻找主人 Necklace 字符串最小表示法

    Description 给定两个项链的表示,判断他们是否可能是一条项链. Input 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的). Output 如果 ...

  5. POJ 1509 Glass Beads【字符串最小表示法】

    题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...

  6. 字符串最小表示法 O(n)算法

    网上看了这篇文章后还是感觉有些地方讲的没有详细的证明所以添加了一点 红色字是博主写的 求字符串的循环最小表示: 上面说的两个字符串同构的,并没有直接先求出Min(s),而是通过指针移动,当某次匹配串长 ...

  7. O - String Problem KMP 字符串最小表示法

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

  8. hdu 2609 字符串最小表示法 虽然不是很懂 还是先贴上来吧。/,。/

    还需要再消化一下这个算法.. 今天没有时间了,, 六级过了 就有大把时间 快活啊!#include<iostream> #include<cstdio> #include< ...

  9. Rabbit的字符串 字符串最小表示法

    Rabbit的字符串 #include<bits/stdc++.h> using namespace std; ; char s[maxn]; int get_min_pos() { , ...

随机推荐

  1. Encrypted bootloader (程序BIN文件加密及在线升级)

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 在上一个博客随笔,我介 ...

  2. 常用操作提高效率 之 for 与in

    问题如何而来: 对于刚参加工作的我  批量删除数据通常采用的是前端传递到后台一个对象的id字符串  通过逗号分隔的多个id  或者收的直接是一个id数组 两个原理一样第一个后台要在次使用split(& ...

  3. 云计算之路-阿里云上:基于Xen的IO模型进一步分析“黑色0.1秒”问题

    在发现云服务器读取OCS缓存的“黑色0.1秒”是发生在socket读取数据时,而且是发生在读取开始的字节,甚至在socket写数据时(比如写入缓存key)也会出现超过50ms的情况,我们的好奇心被激发 ...

  4. CDateTimeUI类源码分析

    CDateTimeUI是duilib里选择日期的控件,继承于CLabelUI控件,用于记录已经选择的日期,选择控件则是调用win32的日期选择控件. CDateTimeUI包含两个类,一个是CDate ...

  5. 「日常训练」Our Tanya is Crying Out Loud (CFR466D2B)

    题意(Codeforces 940B) 对一个数字$x$,你有两个决策:花费$A$减一.或花费$B$除以$k$(但必须可以除尽).问使之到$1$的最少花费. 分析 贼鸡儿简单,但我花式犯蠢……如果除不 ...

  6. 第二十二篇 正在表达式 re模块

    re模块****** 就本质而言,正则表达式时一种小型的,高度专业化的编程语言,在python里,它内嵌在python中,并通过re模块实现.正则表达式模式被编译成一系列的字节码.然后用C编写的匹配引 ...

  7. CSS3 : box-shadow

    box-shadow 用于设置边框阴影,语法: box-shadow: h-shadow v-shadow blur spread color inset; -moz-box-shadow: h-sh ...

  8. Tensorflowonspark安装

    1.实验环境 Centos7+Python3.6+Java8+Hadoop2.6+Spark2.3+Tensorflow1.10.0 2.Tensorflow安装 最简单的方式:pip install ...

  9. docker基础-虚拟化与容器介绍

    正如所有关心docker技术的人所知道的那样,docker是以容器虚拟化为技术为基础的软件,因此在学习docker具体的内容之前,有必要讨论一下虚拟化和容器技术. 虚拟化技术: 在了解虚拟化技术时,各 ...

  10. 网络流——poj1273(入门)

    题目链接:排水沟 题意:现有n个排水沟和m个点(其中1是源点,m是汇点),给定n个排水沟所连接的点,求从源点到汇点的最大流量. [EK解法] #include <algorithm> #i ...