博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符串的最小表示法
阅读量:5248 次
发布时间:2019-06-14

本文共 1359 字,大约阅读时间需要 4 分钟。

现在有个问题需要我们去解决,这个问题是这样的:

有一个字符串,这个字符串的首尾是连在一起的,要求寻找一个位置,使得以该位置为起点的字符串的字典序在所有的字符串中最小

最最暴力的做法就是用O(n)的时间枚举起始位置,O(n)的时间比对字符串的字典序,总的时间复杂度是O(n2),别想了,这种做法肯定不行。

那我们再来看一个稍微朴素点的算法(看的时候最好自己在草稿纸上模拟一下

我们设计ij两个指针。其中i指向最小表示的位置,j作为比较指针。

初始时令i = 0,j = 1 

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

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

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

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

  否则 j += k+1

返回

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

初始时令i=0,j=1 

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

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

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

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

  否则j += k+1

返回ij的较小者

 

注意到上面两个算法唯一的区别是我用荧光笔刷出的那一行。这一行就把复杂度降到O(n)了。

为什么会这样呢?其实我开始看半天也不知道为什么会这样,我后来测试了一下,对于同一道题目,第使用一种算法用了625ms,而第二种只用了16ms!!你就知道差别有多大了。

按我的理解来说,第一种算法仅仅是用i维护了最小表示的位置,j不断往后进行比较;而第二种算法是比较完S[i+k]S[j+k]后根据情况来判断ij谁才是最小表示位置,对应的另外一个值去进行更新比较,这样ij都能用来维护了最小表示的位置,效率会高上很多,妙啊~这种思想好像在哪儿见过,具体的已经忘了,不过以后碰到了理解起来也会更加容易

值得一提的是,可以应用最小表示法判断两个字符串是否同构,与KMP类似,最小表示法处理的是一个字符串S的性质,而不是看论文时给人感觉的处理两个字符串。 只要将两个串的最小表示求出来,然后从最小表示开始比较。剩下的工作就不用多说了。  

Code

int Get_min(){    int n = strlen(s);    int i = 0, j = 1, k = 0, t;    //表示从i开始k长度和从j开始k长度的字符串相同    while(i
0) i += k+1; //i位置大 else j += k+1; //j位置大 if(i==j) j++; k = 0; } } return i >j ?j :i;}
View Code

 参考文章:

转载于:https://www.cnblogs.com/wizarderror/p/11353331.html

你可能感兴趣的文章
持续集成之“Everything is code”
查看>>
在Ubuntu上安装指定版本的Firefox
查看>>
电商网站的宕机案例分析
查看>>
QT 5.1 Beta1 发布,支持静态 Qt 构建
查看>>
eclipse 我来了
查看>>
Counting Pair
查看>>
并行接口和串行接口
查看>>
Python索引页
查看>>
Oracle Pivot学习心得
查看>>
【JAVA并发编程实战】9、锁分段
查看>>
【SCALA】1、我要开始学习scala啦
查看>>
Stripies
查看>>
引包问题
查看>>
查看Linux端口的占用及连接情况
查看>>
让IE浏览器支持CSS3圆角属性的方法
查看>>
020 线程的综合考虑
查看>>
009 IOC--初始化和销毁
查看>>
matlab中的polyfit函数。
查看>>
C# 多线程的代价~内存都被吃了!
查看>>
不规则的组合方向键或功能键
查看>>