字符串的经典算法。
1.KMP算法。
java代码实现如下:
package zuoshen1;
public class KMP {
public static int getIndexOf(String str,String match){
if(str==null||match==null||str.length()<match.length())
return -1;
char[] s=str.toCharArray();
char[] m=match.toCharArray();
int[] next=getNextArr(m);
int si=0;
int mi=0;
while (si<s.length&&mi<m.length){
if(s[si]==m[mi]){
si++;
mi++;
}else if(next[mi]==-1){//已经到m第一个位置了
si++;
}else {//s[si]不等于m[mi]的情况,不需要mi从0开始,直接滑动到next[mi]处
mi=next[mi];
}
}
return mi==m.length?si-mi:-1;
}
public static int[] getNextArr(char[] match){//最大前后缀数组
if(match==null||match.length<1){
return new int[]{-1};
}
int[] next=new int[match.length];
next[0]=-1;
next[1]=0;
int pos=2;//start at 2
int cn=0;
while (pos<match.length){
if(match[pos-1]==match[cn]){//前一个位置和cn相等,扩大cn
next[pos++]=++cn;
}else if(cn>0){//前面还有前后缀
cn=next[cn];
}else {
next[pos++]=0;
}
}
return next;
}
public static void main(String[] args) {
// int[] arr=getNextArr(new char[]{'a','a','a','a','b'});
// for(int num:arr){
// System.out.print(num+" ");
// }
System.out.println(getIndexOf("aaaaaab","aaab"));
}
}
相关题目:
a .给定一个字符串 如何加最短的字符(只能在原始串的后面进行添加)使其构成一个长的字符串且包含两个原始字符串~
思路:其实就是最大前后缀长度数组~ e.g. abcabc ---->abcabcabc 最少增加3个
多求一位nextArr 可以看出之前4个复用 所以再添一位就好~
总结: 在KMP中nextArr数组基础上 多求一位终止位 将不是的补上即可
java参考代码如下:
package zuoshen1;
public class KMP_ShortestHaveTwice {
public static String answer(String str){
if(str==null) return null;
char[] s=str.toCharArray();
if(str.length()==1)
return str+str;
if(str.length()==2)
return s[0]==s[1]?str+String.valueOf(s[0]):str+str;
int cn=getNext(s);
return str+str.substring(cn);
}
public static int getNext(char[] match){
if(match==null||match.length<2){
return -1;
}
int[] next=new int[match.length+1];//比KMP多一位
next[0]=-1;
next[1]=0;
int cn=0;
int pos=2;
while (pos<match.length){
if(match[pos-1]==match[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) {
System.out.println(answer("a"));
System.out.println(answer("aa"));
System.out.println(answer("ab"));
System.out.println(answer("aba"));
System.out.println(answer("abc"));
}
}
b. 给定两个树 判断树2是否为树1的子树 是则返回true
思路: 把一棵树序列化为字符串(字符数组) 如果str2是str1的子串 则T2也是T1的子树。
java参考代码如下:
package zuoshen1;
public class KMP_T1SubtreeEqualsT2 {
public static class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val){
this.val=val;
this.left=null;
this.right=null;
}
}
public static String preorder(TreeNode root){
StringBuilder sb=new StringBuilder();
precore(root,sb);
return sb.toString();
}
public static void precore(TreeNode root,StringBuilder sb){
if(root==null)
return;
sb.append(root.val);
sb.append("#");
if(root.left!=null){
precore(root.left,sb);
}
if(root.right!=null)
precore(root.right,sb);
}
public static boolean isSubtree(TreeNode root1,TreeNode root2){
String s1=preorder(root1);
String s2=preorder(root2);
return KMP.getIndexOf(s1,s2)!=-1?true:false;
}
public static void main(String[] args) {
TreeNode root=new TreeNode(1);
root.left=new TreeNode(2);
root.right=new TreeNode(3);
root.left.left=new TreeNode(4);
root.left.right=new TreeNode(5);
root.right.left=new TreeNode(6);
root.right.right=new TreeNode(7);
TreeNode other=new TreeNode(3);
other.left=new TreeNode(6);
other.right=new TreeNode(7);
System.out.println(preorder(root));
System.out.println(preorder(other));
System.out.println(isSubtree(root,other));
}
}
Manacher算法
原始问题
2.[LeetCode] Longest Palindromic Substring 最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:
Input: “cbbd”
Output: “bb”
我们知道传统的验证回文串的方法就是两个两个的对称验证是否相等,那么对于找回文字串的问题,就要以每一个字符为中心,像两边扩散来寻找回文串,这个算法的时间复杂度是 O(n*n),可以通过 OJ,就是要注意奇偶情况,由于回文串的长度可奇可偶,比如 “bob” 是奇数形式的回文,“noon” 就是偶数形式的回文,两种形式的回文都要搜索,对于奇数形式的,我们就从遍历到的位置为中心,向两边进行扩散,对于偶数情况,我们就把当前位置和下一个位置当作偶数行回文的最中间两个字符,然后向两边进行搜索,参见代码如下: