字符串 最小表示算法
来源:互联网 发布:sql语句是什么 编辑:程序博客网 时间:2024/05/23 16:56
参考自http://blog.csdn.net/cclsoft/article/details/5467743
循环字符串的最小表示法的问题可以这样描述:
对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。
由于语言能力有限,还是用实际例子来解释比较容易:
设S=bcad,且S’是S的循环同构的串。S’可以是bcad或者cadb,adbc,dbca。而且最小表示的S’是adbc。
(1) 对于字符串循环同构的最小表示法,其问题实质是求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)。
(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)了。
这里证明一下为什么 S[i+k] > S[j+k] i=i+k ,
当s[i+k] > s[j+k] 时 i = i+k+1;
这个证明可以转化为证明 从 i ~ i+k 开始 到 i+k结束的前缀 一定大于某个t ( t 在 j~j+k 内 ) 开始的前缀 , 接下来开始证明。
从i ~ i +k 上取一个 ti ,对于 S[ ti ..i+k ] , 这一个字串,显然可以在S[j ....j+k] 上找到一个更小的字串.
例如字符串dbcdbcdbce来说
0 1 2 3 4 5 6 7 8 9
d b c d b c d b c a i = 0 , i + k = 6
d b c d b c a d b c j = 3 , j + k = 9
显然0 ~ 5 上面的子串,一定小于下面的对应位置的子串
所以上式成立
值得一提的是,与KMP类似,最小表示法处理的是一个字符串S的性质,而不是看论文时给人感觉的处理两个字符串。
应用最小表示法判断两个字符串同构,只要将两个串的最小表示求出来,然后从最小表示开始比较。剩下的工作就不用多说了。
#include <bits/stdc++.h>using namespace std;int MinimumRepresentation(char *s,int len){ int i=0,j=1,k=0; //i和j是两个进行比较的起始匹配位点,k是匹配长度 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++;//i和j一定要错开 k = 0;//匹配长度要重置为0 } } return i < j ? i : j ;//因为字典序大的位置被后移了,所以较小的位置就是答案}
- 字符串 最小表示算法
- 【模板】字符串算法-字符串最小表示法
- 【模板】字符串算法-字符串最小表示法
- 字符串最小表示法 O(n)算法
- 字符串最小表示法 O(n)算法
- 字符串 最小表示法 O(n)算法
- 字符串最小表示法 O(n)算法
- 字符串最小表示模板
- 字符串最小表示
- 字符串的最小表示
- 字符串最小表示法
- 字符串最小表示法
- ZOJ2006 字符串最小表示
- 字符串最小表示法(1) 朴素算法
- 字符串 最小表示法 O(n)算法 【模板】
- 【字符串最小表示】HDU 3374
- 【字符串最小表示】HDU 2609
- POJ 1509(字符串最小表示)
- 注册广播接收者的两种方式
- oracle按照日期字段进行查询/oracle定时任务
- 时间久了不访问站点站点会变得很慢
- 大型网站之分布式会话管理
- jquery.cookie() 方法的使用(读取、写入、删除)
- 字符串 最小表示算法
- 【转载】git/github初级运用自如
- 错误收集检讨(1)
- 创建ajax过程
- 学习知乎日报--day2
- android studio生成jar包
- 2016.09.22------oracle连接使用、this
- MFC在位图上方绘制文字
- java中类型的输入(Scanner)