privatestaticint[] generateNext(String s) { int[] next = newint[s.length()]; //从第2位开始,因为第0位没有前缀;第1位只有一个前缀字符(0位字符),这种情况在第1位出现了不匹配,只能将第0位拿来对齐,所以干脆就直接赋值为0了 for (int i = 2; i < s.length(); i++) { //第i个字符的前缀字符串中,能拼接出(i-1)个有效前缀子串,因为要排除掉整个前缀字符串的情况,这种情况直接赋值为0,重新开始匹配 int j = i - 1; while (j > 0) {//遍历每一个前缀子串和与之对应的后缀子串 int length = i - j;//子串的长度 int m = 0;//前缀子串起始位置 int n = j;//后缀子串起始位置 boolean match = true;//是否完全匹配 for (int k = 0; k < length; k++) { if (s.charAt(m) != s.charAt(n)) { match = false; break; } m++; n++; } if (match) {//前后缀子串完全匹配,那么第i位置字符对应的next直接就恰好是length这个值 next[i] = length; } //我们计算的是最长的前缀串,所以需要继续遍历更长的前缀子串 j--; } } return next; }
privatestaticintkmp(String str, String pattern){ int[] next = generateNext(pattern); for (int i = 0; i < next.length; i++) { System.out.print(next[i] + ","); } //j用来遍历模式串 int j = 0; //i遍历主串 for (int i = 0; i < str.length(); i++) { //如果出现不相等的情况,找出模式串的下一个位置 while (j > 0 && str.charAt(i) != pattern.charAt(j)) { j = next[j]; } //相等,比较下一个 if (str.charAt(i) == pattern.charAt(j)) { j++; } //下一个到末尾,证明匹配完成 if (j == pattern.length()) { return i - pattern.length() + 1; } } return -1; }
publicstaticvoidmain(String[] args){ String str = "acbccddddddfeeffde"; String pattern = "fee"; int index = kmp(str, pattern); System.out.println("首次出现位置:" + index); }
排序算法
公用交换位置的方法:
1 2 3 4 5 6
voidswap(int[] arr,int i,int j){ int t = arr[i]; arr[i] = arr[j]; arr[j] = t; }
publicstaticvoidselectSort(int[] list){ for (int i = 0; i < list.length; i++) { for (int j = i + 1; j < list.length; j++) { if (list[j] < list[i]) swap(list, i, j); }
publicstaticintpartition(int[] list, int from, int to){ int val = list[from]; int p1 = from; int p2 = to + 1; while (true) { while (list[++p1] < val) { if (p1 == to) break; } while (list[--p2] > val) { if (p2 == from) break; } if (p1 >= p2) break; swap(list, p1, p2); } swap(list, p2, from); return p2; }
publicstaticvoidquickSort(int[] list, int from, int to){ if (from >= to) return;//一定是大于等于!! int p = partition(list, from, to); quickSort(list, from, p - 1); quickSort(list, p + 1, to); }
publicstaticvoidmain(String[] args){ int[] a = newint[]{39, 8, 45, 3, 91, 28, 4, 60, 49, 7, 1, 24, 92}; new HeapSort().heapSort(a); for (int i = 0; i < a.length; i++) { System.out.print(a[i] + ", "); }
}
voidswap(int[] arr, int i, int j){ int t = arr[i]; arr[i] = arr[j]; arr[j] = t; }
//下沉函数,i是被下沉的位置,len是下沉的边界 voidsink(int[] arr, int i, int len){ int left = 2 * i + 1;//左子节点 int right = 2 * i + 2;//右子节点 int largest = i;//三个节点中,值最小的那个位置 if (left < len && arr[left] < arr[largest]) { largest = left; } if (right < len && arr[right] < arr[largest]) { largest = right; } if (largest != i) {//如果不是父结点,说明发生了下沉,需要对下沉的结点继续下沉 swap(arr, i, largest); sink(arr, largest, len); } }
//构建最小堆,只需要下沉前半部分结点 voidbuildMinHeap(int[] arr){ for (int i = arr.length / 2; i >= 0; i--) { sink(arr, i, arr.length); } }
voidheapSort(int[] arr){ buildMinHeap(arr); //排序,构建完最小堆的数组,第0个位置就是最小的,把它与最后的位置交换,然后对0位置下沉,就会选出这个新的堆的最小数,重复这个步骤 for (int i = arr.length - 1; i > 0; i--) { swap(arr, 0, i); sink(arr, 0, i); } } }