赞
踩
给出一个字符串,比如abcdefg
我们可以选择任意一个字符作为字符传的开始位置,比如选择a, 得到字符串abcdefg
, 选择b得到bcdefga
, 选择c得到cdefgab
… 选择g得到gabcdefg
, 其中的最大表示即位字典序最大的一个选择: gabcdefg
, 最小表示积为字典序最小的一个选择: abcdefg
// 最小表示法 public static String minPresentStr(String s){ int i = 0, j = 1, k = 0, n = s.length();//i j初始指向两个可能的位置 while (i < n && j < n && k < n) { if (s.charAt((i + k) % n) == s.charAt((j + k) % n)) {//1. k++;//遇到的字符一样 继续查找 } else { if (s.charAt((i + k) % n) > s.charAt((j + k) % n)) { i = i+1;//s[i+k]>s[j+k] 以s[i]开头的字符串字典序一定大于s[j]开头的字符串的字典序 i往后移动一个位置 期待找到更小的s[i]<s[j] } else if (s.charAt((i + k) % n) < s.charAt((j + k) % n)) { j = j + 1;//s[i+k]<s[j+k] 以s[j]开头的字符串字典序一定大于s[i]开头的字符串的字典序 j往后移动一个位置 期待找到更小的s[j]<s[i] } if (i == j) {//相等时往后移动i或j一个位置 不移动的话会导致1处的if一直成立 这样就找不出答案了 i++; } k = 0; } } int start = Math.min(i, j);//最后结果取i j中的最小值 return s.substring(start, n) + s.substring(0, start); }
// 最大表示法 public static String maxPresentStr(String s){ int i = 0, j = 1, k = 0, n = s.length(); while (i < n && j < n && k < n) { if (s.charAt((i + k) % n) == s.charAt((j + k) % n)) { k++; } else { if (s.charAt((i + k) % n) > s.charAt((j + k) % n)) { j = j+1; } else if (s.charAt((i + k) % n) < s.charAt((j + k) % n)) { i = i + 1; } if (i == j) { i++; } k = 0; } } int start = Math.min(i, j); return s.substring(start, n) + s.substring(0, start); }
每次比较i和j开始的循环同构,把当前比较到的位置记作 ,每次遇到不一样的字符时便把大的/小的跳过,最后剩下的就是最优解
对于aaaaab
这种特殊的字符串 , 不难发现这个算法的复杂度退化为
O
(
n
2
)
O(n^2)
O(n2) 。
假设以位置i开始的字符串为s[i,i+k] 以位置j开始的字符串为s[j,j+k] 这两个字符串的长度为k+1, 假设这两个字符串的前k个字符相同,即s[i:i+k-1]==s[j:j+k-1]
只有最后一个字符s[i+k]!=s[j+k]
假设s[i+k]>s[j+k]
:
那么以i~i+k
范围内的任意一个位置作为开始位置形成的字符串,都会有一个以j~j+k
位置开始的字符串,后者的字典序更小
原因: 如果以s[i+k]
开始,那么以s[j+k]
一定更优, 如果以s[i+p]
开始(
0
<
=
p
<
=
k
−
1
0<=p<=k-1
0<=p<=k−1), 那么一定有s[i+q]
(
0
<
=
q
<
=
k
−
1
0<=q<=k-1
0<=q<=k−1)更优,可以挑选s[j+q]
使得s[j+q]=s[i+p]
, 这样s[i+p:i+k-1]=s[j+q:j+k-1]
(前k个字符相同是前提条件), 但是s[i+p]开始的字符串会保含s[i+k], s[j+q]开始的字符串会保含s[[j+k], 这样前面一样,最后一个字符后者的字典序较小,因此后者的字符串整体字典序较小
根据上面的讨论,当s[i+k]>s[j+k]
时,暴力法中时将i往后移动一个位置,实际上可以将i往后移动k+1个位置,这就是优化所在
//优化后的最小表示法 public static String minPresenrStr(String s){ int i = 0, j = 1, k = 0, n = s.length(); while (i < n && j < n && k < n) { if (s.charAt((i + k) % n) == s.charAt((j + k) % n)) { k++; } else { if (s.charAt((i + k) % n) > s.charAt((j + k) % n)) { i = i + k + 1; } else if (s.charAt((i + k) % n) < s.charAt((j + k) % n)) { j = j + k + 1; } if (i == j) { i++; } k = 0; } } int start = Math.min(i, j); return s.substring(start, n) + s.substring(0, start); }
//优化后的最大表示法 public static String maxPresenrStr(String s){ int i = 0, j = 1, k = 0, n = s.length(); while (i < n && j < n && k < n) { if (s.charAt((i + k) % n) == s.charAt((j + k) % n)) { k++; } else { if (s.charAt((i + k) % n) > s.charAt((j + k) % n)) { j = j + k + 1; } else if (s.charAt((i + k) % n) < s.charAt((j + k) % n)) { i = i + k + 1; } if (i == j) { i++; } k = 0; } } int start = Math.min(i, j); return s.substring(start, n) + s.substring(0, start); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。