KMP算法
来源:互联网 发布:数控车大螺距螺纹编程 编辑:程序博客网 时间:2024/06/06 14:16
2015-5-31
今天在leetcode上遇到一个问题,shortest palindrome
由此想到了字符串查找的高效一点的算法
先介绍kmp算法:
使用kmp算法可以将字符串搜索的时间复杂度降到 O(m+n),m和n分别是original和find字符串的长度。(当然还有改进的空间=。=
这个算法的主要思想是,当匹配失败的失败的适合,不是从下一个字符开始尝试匹配,而是充分利用已经匹配的信息,一次跳多个字符去匹配
具体做法是,先对find字符串求next数组,next[i]的含义是,从find字符串中前缀和后缀相同的最大长度,例如:ababab,next[3]表示的是子字符串aba的前缀和后缀相同的最大长度,即1。以下是java实现
public int[] getNext(String b){ int len=b.length(); int j=0; int next[]=new int[len+1];//next表示长度为i的字符串前缀和后缀的最长公共部分,从1开始 next[0]=next[1]=0; for(int i=1;i<len;i++)//i表示字符串的下标,从0开始 {//j在每次循环开始都表示next[i]的值,同时也表示需要比较的下一个位置 while(j>0&&b.charAt(i)!=b.charAt(j))j=next[j]; if(b.charAt(i)==b.charAt(j))j++; next[i+1]=j; } return next;}
根据这个next数组,在original中查找find
假设j为当前累计匹配成功的子字符串长度,方法是每次遇到匹配失败的,就找next[j],看next[j]处是否匹配成功,若匹配成功则继续向下匹配,若失败,则再找next[next[j]]如此下去直到到0。以下是java实现
public void search(String original, String find, int next[]) { int j = 0; for (int i = 0; i < original.length(); i++) { while (j > 0 && original.charAt(i) != find.charAt(j)) j = next[j]; if (original.charAt(i) == find.charAt(j)) j++; if (j == find.length()) { System.out.println("find at position " + (i - j)); System.out.println(original.subSequence(i - j + 1, i + 1)); j = next[j]; } }}
回到原题
我的思路是找到字符串中以第一个字母为起点的最长回文子字符串,找到之后,就只要把剩下的字符串倒叙放在原来的字符串前面,以示例输入(‘aacecaaa’)为例,它的最长回文子字符串是aacecaa,最后在前面加个a便可。
具体步骤 :
1. 使用getnext函数得到string的next数组。
2. 接下来就是找从string末尾开始向前的子字符串中,能匹配的string前缀的最大长度,终止条件为两个字符串第一次“遇到”,此时便找到了以string首字母为首的最大回文子字符串。例如“aacecaaa”,就从最后一个a开始向前,找匹配“aacecaaa”本身的字符串,search中的终结条件改为,当从前到后匹配的位置和从后向前匹配的位置有交叉时停止。
幸运的是,实现这个功能只要把search函数稍微改一下即可,下面是具体的java代码
public String search(String original, int next[]) { int j = 0; char[] result=null; int length=original.length(); for (int i = original.length()-1; i >= 0; i--) { while (j > 0 && original.charAt(i) != original.charAt(j)) j = next[j]; if (original.charAt(i) == original.charAt(j)) j++; if (j==i) { result=new char[(length-j)*2]; int r_len=result.length; for(int t=0;t<length-j;t++){ result[t]=original.charAt(length-1-t); result[r_len-1-t]=result[t]; } }else if(j==i+1){ result=new char[2*length-j*2+1]; int r_len=result.length; for(int t=0;t<length-j;t++){ result[t]=original.charAt(length-1-t); result[r_len-1-t]=result[t]; } result[length-j]=original.charAt(j-1); } } return new String(result); }
- KMP算法详解 【KMP】
- 【KMP】KMP算法模板
- KMP hihoCoder1015 KMP算法
- kmp算法
- KMP算法
- KMP算法
- KMP算法
- KMP算法
- KMP 算法
- kmp算法
- KMP算法
- kmp算法
- KMP算法
- KMP算法
- kmp算法
- kmp算法
- KMP算法
- KMP算法
- 关于删记录释放表空间的测试
- word宏批量处理图片大小
- linux程序设计——入门(第一章)
- 找出1001个数(区间1~1000)中重复出现的数(有两个相同)
- Setup Local Yum Repository On CentOS 7
- KMP算法
- freemarker list (长度,遍历,下标,嵌套,排序)
- CSS定位
- How to Install GUI (Gnome 3) Using CD/DVD on RHEL/CentOS 7
- IE 6 7 8获取文本框中光标的位置
- java内存划分
- QT5.3 杂记 Qt5下,QWidget系列从QtGui中被剥离出去,成为单独的QtWidget模块。随着Qt Quick2的引入,QtDeclarative也逐渐和QWidget系列也脱离关系。
- iOS编程——多态
- JAVA微信公众号开发入门