标签:har array 问题 没有 第k大 第七章 toc res ring
KMP算法解决的问题:在str1字符串(长度n)中是否包含str2(长度m),返回-1或者首位置
next[]数组:[i]
存储的是模式串在i
位置前的子串中,其前缀和后缀最长的匹配长度
aaaa
,前缀a
=后缀a
,前缀aa
=后缀aa
,前缀aaa
=后缀aaa
,规定前后缀为子串真子集,所以最长前后缀匹配长度为3。 public static int getIndexOf(String s, String m) { //kmp算法
if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
return -1;
}
char[] ss = s.toCharArray(); // 匹配串(是否包含模式串)
char[] ms = m.toCharArray(); // 模式串
int si = 0;
int mi = 0;
int[] next = getNextArray(ms);
while (si < ss.length && mi < ms.length) {
if (ss[si] == ms[mi]) {
si++;
mi++;
} else if (next[mi] == -1) {
si++;
} else {
mi = next[mi];
}
}
return mi == ms.length ? si - mi : -1;
}
public static int[] getNextArray(char[] ms) { //求解next数组
if (ms.length == 1) {
return new int[] { -1 };
}
int[] next = new int[ms.length];
next[0] = -1;
next[1] = 0;
int pos = 2; //求解位置
int cn = 0; //前索引的对称位置
while (pos < next.length) {
if (ms[pos - 1] == ms[cn]) {
next[pos++] = ++cn;
} else if (cn > 0) {
cn = next[cn];
} else {
next[pos++] = 0;
}
}
return next;
}
public static void main(String[] args) {
String str = "abcabcababaccc";
String match = "ababa";
System.out.println(getIndexOf(str, match));
}
题目表述:给定一个字符串str1,只能往str1的后面添加字符变成str2。要求一:str2必须包含两个str1,两个str1可以有重合,但是不能以同一位置开头(不能完全重合)。要求二:str2尽量短。最终返回str2。
思路:
算法实现(java)
public static String answer(String str) {
if (str == null || str.length() == 0) {
return "";
}
char[] chas = str.toCharArray();
if (chas.length == 1) {
return str + str;
}
if (chas.length == 2) {
return chas[0] == chas[1] ? (str + String.valueOf(chas[0])) : (str + str);
}
int endNext = endNextLength(chas);
return str + str.substring(endNext);
}
public static int endNextLength(char[] chas) { // 就是求解next数组,只不过直接返回next[]位置上的值即可。
int[] next = new int[chas.length + 1];
next[0] = -1;
next[1] = 0;
int pos = 2;
int cn = 0;
while (pos < next.length) {
if (chas[pos - 1] == chas[cn]) {
next[pos++] = ++cn;
} else if (cn > 0) {
cn = next[cn];
} else {
next[pos++] = 0;
}
}
return next[next.length - 1];
}
public static void main(String[] args) {
String test1 = "a";
System.out.println(answer(test1));
String test2 = "aa";
System.out.println(answer(test2));
String test3 = "ab";
System.out.println(answer(test3));
String test4 = "abcdabcd";
System.out.println(answer(test4));
String test5 = "abracadabra";
System.out.println(answer(test5));
}
题目表述:给定两个二叉树T1和T2,返回T1的某个子树是否与T2的结构相等(就是T2为T1的某一子树)
#
特殊字符表示,每走一个结点输出再加上_
(一个表示结束一个表示空)。eg. 1_2_#_#_3_#_#_
,表示1->2左3右的一棵二叉树。(使用前+中序这种还原树方法是没有办法还原结点数据全都相同的情况)思路:
12_#_#_
和2_#_#_
)算法实现(java)
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static boolean isSubtree(Node t1, Node t2) {
String t1Str = serialByPre(t1);
String t2Str = serialByPre(t2);
return getIndexOf(t1Str, t2Str) != -1;
}
public static String serialByPre(Node head) {
if (head == null) {
return "#!";
}
String res = head.value + "!";
res += serialByPre(head.left);
res += serialByPre(head.right);
return res;
}
// KMP
public static int getIndexOf(String s, String m) {
if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
return -1;
}
char[] ss = s.toCharArray();
char[] ms = m.toCharArray();
int[] nextArr = getNextArray(ms);
int index = 0;
int mi = 0;
while (index < ss.length && mi < ms.length) {
if (ss[index] == ms[mi]) {
index++;
mi++;
} else if (nextArr[mi] == -1) {
index++;
} else {
mi = nextArr[mi];
}
}
return mi == ms.length ? index - mi : -1;
}
public static int[] getNextArray(char[] ms) {
if (ms.length == 1) {
return new int[] { -1 };
}
int[] nextArr = new int[ms.length];
nextArr[0] = -1;
nextArr[1] = 0;
int pos = 2;
int cn = 0;
while (pos < nextArr.length) {
if (ms[pos - 1] == ms[cn]) {
nextArr[pos++] = ++cn;
} else if (cn > 0) {
cn = nextArr[cn];
} else {
nextArr[pos++] = 0;
}
}
return nextArr;
}
public static void main(String[] args) {
Node t1 = new Node(1);
t1.left = new Node(2);
t1.right = new Node(3);
t1.left.left = new Node(4);
t1.left.right = new Node(5);
t1.right.left = new Node(6);
t1.right.right = new Node(7);
t1.left.left.right = new Node(8);
t1.left.right.left = new Node(9);
Node t2 = new Node(2);
t2.left = new Node(4);
t2.left.right = new Node(8);
t2.right = new Node(5);
t2.right.left = new Node(9);
System.out.println(isSubtree(t1, t2));
}
求解最长的回文子串
RC与当前遍历i的关系:
算法实现(java)
public static char[] manacherString(String str) {
char[] charArr = str.toCharArray();
char[] res = new char[str.length() * 2 + 1];
int index = 0;
for (int i = 0; i != res.length; i++) {
res[i] = (i & 1) == 0 ? ‘#‘ : charArr[index++];
}
return res;
}
public static int maxLcpsLength(String str) {
if (str == null || str.length() == 0) {
return 0;
}
char[] charArr = manacherString(str);
int[] pArr = new int[charArr.length];
int index = -1;
int pR = -1;
int max = Integer.MIN_VALUE;
for (int i = 0; i != charArr.length; i++) {
pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;
while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
pArr[i]++;
else {
break;
}
}
if (i + pArr[i] > pR) {
pR = i + pArr[i];
index = i;
}
max = Math.max(max, pArr[i]);
}
return max - 1;
}
public static void main(String[] args) {
String str1 = "abc1234321ab";
System.out.println(maxLcpsLength(str1));
}
题目表述:给定一个字符串str1,只能往str1的后面添加字符变成str2,要求str2整体都是回文串且最短。eg. str1=ABC12321,返回ABC12321CBA。
思路:
public static char[] manacherString(String str) {
char[] charArr = str.toCharArray();
char[] res = new char[str.length() * 2 + 1];
int index = 0;
for (int i = 0; i != res.length; i++) {
res[i] = (i & 1) == 0 ? ‘#‘ : charArr[index++];
}
return res;
}
public static String shortestEnd(String str) {
if (str == null || str.length() == 0) {
return null;
}
char[] charArr = manacherString(str);
int[] pArr = new int[charArr.length];
int index = -1;
int pR = -1;
int maxContainsEnd = -1;
for (int i = 0; i != charArr.length; i++) {
pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;
while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
pArr[i]++;
else {
break;
}
}
if (i + pArr[i] > pR) {
pR = i + pArr[i];
index = i;
}
if (pR == charArr.length) {
maxContainsEnd = pArr[i];
break;
}
}
char[] res = new char[str.length() - maxContainsEnd + 1];
for (int i = 0; i < res.length; i++) {
res[res.length - 1 - i] = charArr[i * 2 + 1];
}
return String.valueOf(res);
}
public static void main(String[] args) {
String str2 = "abcd123321";
System.out.println(shortestEnd(str2));
}
// O(N*logK)
public static int[] getMinKNumsByHeap(int[] arr, int k) {
if (k < 1 || k > arr.length) {
return arr;
}
int[] kHeap = new int[k];
for (int i = 0; i != k; i++) {
heapInsert(kHeap, arr[i], i);
}
for (int i = k; i != arr.length; i++) {
if (arr[i] < kHeap[0]) {
kHeap[0] = arr[i];
heapify(kHeap, 0, k);
}
}
return kHeap;
}
public static void heapInsert(int[] arr, int value, int index) {
arr[index] = value;
while (index != 0) {
int parent = (index - 1) / 2;
if (arr[parent] < arr[index]) {
swap(arr, parent, index);
index = parent;
} else {
break;
}
}
}
public static void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int largest = index;
while (left < heapSize) {
if (arr[left] > arr[index]) {
largest = left;
}
if (right < heapSize && arr[right] > arr[largest]) {
largest = right;
}
if (largest != index) {
swap(arr, largest, index);
} else {
break;
}
index = largest;
left = index * 2 + 1;
right = index * 2 + 2;
}
}
// O(N)
public static int[] getMinKNumsByBFPRT(int[] arr, int k) {
if (k < 1 || k > arr.length) {
return arr;
}
int minKth = getMinKthByBFPRT(arr, k);
int[] res = new int[k];
int index = 0;
for (int i = 0; i != arr.length; i++) {
if (arr[i] < minKth) {
res[index++] = arr[i];
}
}
for (; index != res.length; index++) {
res[index] = minKth;
}
return res;
}
public static int getMinKthByBFPRT(int[] arr, int K) {
int[] copyArr = copyArray(arr);
return select(copyArr, 0, copyArr.length - 1, K - 1);
}
public static int[] copyArray(int[] arr) {
int[] res = new int[arr.length];
for (int i = 0; i != res.length; i++) {
res[i] = arr[i];
}
return res;
}
public static int select(int[] arr, int begin, int end, int i) {
if (begin == end) {
return arr[begin];
}
int pivot = medianOfMedians(arr, begin, end);
int[] pivotRange = partition(arr, begin, end, pivot);
if (i >= pivotRange[0] && i <= pivotRange[1]) {
return arr[i];
} else if (i < pivotRange[0]) {
return select(arr, begin, pivotRange[0] - 1, i);
} else {
return select(arr, pivotRange[1] + 1, end, i);
}
}
public static int medianOfMedians(int[] arr, int begin, int end) {
int num = end - begin + 1;
int offset = num % 5 == 0 ? 0 : 1;
int[] mArr = new int[num / 5 + offset];
for (int i = 0; i < mArr.length; i++) {
int beginI = begin + i * 5;
int endI = beginI + 4;
mArr[i] = getMedian(arr, beginI, Math.min(end, endI));
}
return select(mArr, 0, mArr.length - 1, mArr.length / 2);
}
public static int[] partition(int[] arr, int begin, int end, int pivotValue) {
int small = begin - 1;
int cur = begin;
int big = end + 1;
while (cur != big) {
if (arr[cur] < pivotValue) {
swap(arr, ++small, cur++);
} else if (arr[cur] > pivotValue) {
swap(arr, cur, --big);
} else {
cur++;
}
}
int[] range = new int[2];
range[0] = small + 1;
range[1] = big - 1;
return range;
}
public static int getMedian(int[] arr, int begin, int end) {
insertionSort(arr, begin, end);
int sum = end + begin;
int mid = (sum / 2) + (sum % 2);
return arr[mid];
}
public static void insertionSort(int[] arr, int begin, int end) {
for (int i = begin + 1; i != end + 1; i++) {
for (int j = i; j != begin; j--) {
if (arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
} else {
break;
}
}
}
}
public static void swap(int[] arr, int index1, int index2) {
int tmp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = tmp;
}
public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = { 6, 9, 1, 3, 1, 2, 2, 5, 6, 1, 3, 5, 9, 7, 2, 5, 6, 1, 9 };
// sorted : { 1, 1, 1, 1, 2, 2, 2, 3, 3, 5, 5, 5, 6, 6, 6, 7, 9, 9, 9 }
printArray(getMinKNumsByHeap(arr, 10));
printArray(getMinKNumsByBFPRT(arr, 10));
}
算法<初级> - 第七章 KMP/Manacher/BFPRT算法(完结)
标签:har array 问题 没有 第k大 第七章 toc res ring
原文地址:https://www.cnblogs.com/ymjun/p/12746173.html