做了一个问题突然想到可以用Kmp解决,所以看了一下自己之前写的关于Kmp的博客用JAVA实现的KMP匹配子串,记录一下,省的又忘了。

/*
*题目描述:
* 假定我们都知道非常高效的算法来检查一个单词是否为其他字符串的子串。
* 请将这个算法编写成一个函数,给定两个字符串s1和s2,请编写代码检查s2是否为s1旋转而成,要求只能调用一次检查子串的函数。
* 给定两个字符串s1,s2,请返回bool值代表s2是否由s1旋转而成。
* 字符串中字符为英文字母和空格,区分大小写,字符串长度小于等于1000。
*/

/*
*解题思路:
*
*方案1:
*分别比较字符串的原串和旋转串的前半段和旋转部分的后半段,两段都相同即返回true.
*时间复杂度为O(n2)
*
*方案2:
*假设原字符串有ABCD四个部分,旋转子串则有BCDA->CDAB->DABC->ABCD四种这四种都是ABCDABCD的子串,
*所以就将原问题转化为了判断新串是否是原串+原串的子串的问题.
*可以采用系统自带的contains函数或者kmp算法解决匹配子串的问题.
*/
解决代码如下:

public int[] getNext(String str)
{
if(str == null || str.length() == 0)
{
return null;
} int strLen = str.length();
int next[] = new int[strLen+1]; //next数组表示,长度为i的字符串最长公共前后缀的长度为next[i],所以需要多一个空间
next[0] = next[1] = 0; int j;
for(int i = 1; i < strLen; i++)
{
j = next[i]; if(str.charAt(i) == str.charAt(j))
{
next[i+1] = next[i] + 1; //直接找到不用计算
}
else
{//继续寻找next[next[i]]
while(j > 0 && str.charAt(i) != str.charAt(j))
{
j = next[j]; //递归查找next[],直到找到字符相等或next[1];
} if(str.charAt(i) == str.charAt(j))
{
next[i+1] = next[j] + 1; //next
}
else
{
next[i+1] = 0;
}
}
} return next;
} public boolean findsubString(String originStr,String findStr,int next[])
{
if(originStr == null || findStr == null || originStr.length() == 0 || findStr.length() == 0)
{
return false;
} int matchLen = 0; //上一次已匹配的长度
for(int i = 0; i < originStr.length(); i++)
{
if(originStr.charAt(i) == findStr.charAt(matchLen))
{
matchLen++;
if(matchLen == findStr.length())
{//找到子串
return true;
}
}
else
{//通过next数组计算出findStr跳转的位置
while(matchLen > 0 && originStr.charAt(i) != findStr.charAt(matchLen))
{
matchLen = next[matchLen];
}
}
} return false;
} public boolean checkReverseEqual(String s1, String s2)
{ if(s1 == null || s2 == null)
{
return false;
} int oldLen = s1.length(),newLen = s2.length(); if(oldLen != newLen)
{
return false;
} String s3 = s1 + s1;
int next[] = getNext(s2); return findsubString(s3,s2,next); /*
方法2
String s3 = s1 + s1;
return s3.contains(s2);
*/ /*
方法3
int oldIndex;
boolean flag = true; for(int i = 0; i < oldLen; i++)
{
oldIndex = i;
flag = true; if(s1.charAt(i) == s2.charAt(0))
{
//比较旋转的前半段
int newIndex;
for(newIndex = 0; oldIndex + newIndex < oldLen; newIndex++)
{
if(s1.charAt(oldIndex + newIndex) != s2.charAt(newIndex))
{
flag = false;
break;
}
} if(flag == true)
{
//比较旋转的后半段
for(int k = 0; k < oldIndex; k++)
{
if(s1.charAt(k) != s2.charAt(newIndex + k))
{//newIndex + k防止新串不偏移
flag = false;
break;
}
}
} if(flag == true)
{
return true;
}
}
}
*/
}

最新文章

  1. BZOJ 2815: [ZJOI2012]灾难
  2. Scene
  3. 《你是我的小羊驼》游戏源码 v1.0
  4. SQL Server 一些关键字详解(一)
  5. javascript日用代码集合(一)
  6. git学习利器:《Git Pro》中文版
  7. thrift之TTransport类体系原理及源码详细解析1-类结构和抽象基类
  8. android 控件的移动
  9. IC卡
  10. iOS App集成Apple Pay教程(附示例代码)
  11. python 自动化运维项目_目录
  12. easyui datagrid行中点击a标签链接,行被选中,但是获取不到对应的参数
  13. [原创]Floodlight+ovs的基本使用
  14. 使用插件bootstrap-table实现表格记录的查询、分页、排序等处理
  15. 六大设计原则(四)ISP接口隔离原则(上)
  16. 5种PHP创建数组的方式
  17. 在Windows Server 2008 R2 Server中,上传视频遇到的问题(二)
  18. hdu2174 kiki&#39;s game 博弈
  19. eclipse中查找某一个字符串
  20. Java - 集成开发环境Eclipse的使用方法和技巧

热门文章

  1. “/usr/local/lib/libosipparser2.so.7: could not read symbols: Invalid operation” 异常解决
  2. VUE:页面跳转时传递参数,及参数获取
  3. WebStorm ------------ 调整字体大小和背景
  4. Ansible13:Playbook循环语句
  5. 谷歌浏览器扩展程序中安装vue-devtools插件
  6. MySql Packet for query is too large问题解决方案
  7. [转帖]进程状态的转换与PCB详解
  8. JDK安装及配置——Linux系统
  9. VS代码调试出现:当前不会命中断点。还没有为该文档加载任何符号。
  10. “分而治之”,一种AI和动画系统的架构