leetcode 459. Repeated Substring Pattern

257 篇文章 17 订阅

Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000.

Example 1:

Input: "abab"

Output: True

Explanation: It's the substring "ab" twice.

Example 2:

Input: "aba"

Output: False

Example 3:

Input: "abcabcabcabc"

Output: True

Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.)
注意这道题不能用递归,不然会stack overflow。

  1. 重复字符串的长度 一定是整个字符串长度 的除数
  2. 找到 str.length 的所有可能的除数,从length/2 来开始找。
  3. 如果 i 是 str.length 的除数,那么重复叠加子字符串直到长度和s.length 相等为止。
  4. 如果获得的字符串和输入的 str 相等,返回true 。

public boolean repeatedSubstringPattern(String s) {
	int n=s.length();
	for(int sub_len=s.length()/2;sub_len>=1;sub_len--){
		if(n%sub_len==0){
			int times=n/sub_len;
			String subString=s.substring(0,sub_len);
			StringBuilder sb=new StringBuilder();
			for(int i=0;i<times;i++){
				sb.append(subString);
			}
			if(sb.toString().equals(s)){
				return true;
			}
		}
	}
	return false;
}
还有大神用了一种很奇妙的思路:

假设输入是 S="helloworld". 现在给了另外一个字符串 T="lloworldhe", 我们如何确认 T 是 S 旋转后的一个版本?可以检查 S 是否是of T+T 的子串。

那么我们如何将这个结论应用到该问题上呢?我们假设 S 的每个旋转版本,比如假设它旋转了从左开始的 k 个单元 [k < len(S)] ,确切地说,我们看这些字符串 "elloworldh", "lloworldhe", "loworldhel", 等等...

如果我们要判断一个周期性的字符串 (i.e. is made up of strings that are the same and repeat R times), 那么我们可以检查是否 该字符串 和 它的某个旋转版本 是一样的。如果存在,那么这个字符串是周期性的。检查 S 是否是 (S+S)[1:-1] (意思是S+S去掉头字符和尾字符) 的子串。

如果 S 由重复子串组成,那么可以被表示为 S = AA (比如,这里 S 有两个重复子串)
那么我们重复 S, SS=AAAA.
去掉第一个字符和最后一个字符,我们产生一个新字符串: S2=XAAY.

如果该字符串是由重复子串组成,那么S2 中应该包含 S 。

public boolean repeatedSubstringPattern(String s) {
        String c = (s + s).substring(1, s.length() + s.length() - 1);
        return c.indexOf(s) != -1;
}

还有大神用KMP做。


n-len: the length of prefix(should be the repeated sequence),
n%(n-len): check if the candidate sequence is the answer.

public boolean repeatedSubstringPattern(String str) {
	//This is the kmp issue
	int[] prefix = kmp(str);
	int len = prefix[str.length()-1];
	int n = str.length();
	return (len > 0 && n%(n-len) == 0);
}
private int[] kmp(String s){
	int len = s.length();
	int[] res = new int[len];
	char[] ch = s.toCharArray();
	int i = 0, j = 1;
	res[0] = 0;
	while(i < ch.length && j < ch.length){
	     if(ch[j] == ch[i]){
	          res[j] = i+1;
	          i++;
	          j++;
	     }else{
	          if(i == 0){
	               res[j] = 0;
	               j++;
	          }else{
	               i = res[i-1];
	          }
	     }
	}
	return res;
}

KMP详见:http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/

我觉得KMP问题肯定之后有更加典型的leetcode题,因此我这里就不详细解释了。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值