设计一个函数hasCheated(String s1,String s2,int N),如果两个字符串
s1, s2
具有至少长度为N的公共子字符串,则返回true。不使用.contains,.substring
是否需要转换为char数组或类似的方法?
我正在考虑找到最长的公共子字符串,然后再次查看它N
。这有什么办法?
答案 0 :(得分:2)
首先找到最长的公共子串比检查是否存在至少给定大小的匹配要慢。你可以在获得比赛后立即停止,即使可能有更长的比赛。
我会构建一个哈希集(或者如果需求更复杂的哈希映射),它表示长度为N的所有子字符串(没有实际创建那些子字符串)并使用它来扫描长度为N的字符串匹配。
您可以在O(M)时间内执行此操作,其中M是最长字符串的长度。
您可以像这样创建一个子字符串类。
class Substring {
final String s;
final int offset, length, hashCode;
Substring(String s, int offset, int length) {
this.s = s;
this.offset = offset;
this.length = length;
this.hashCode = hashCode(s, offset, length); // define to taste
}
public int hashCode() { return hashCode; }
public boolean equals(Object o) {
if (!(o instanceof Substring)) return false;
Substring ss = (Substring) s;
if (hashCode != ss.hashCode || length != ss.length) return false;
for (int i = 0; i < length; i++)
if (s.charAt(i) != ss.s.charAt(i))
return false;
return true;
}
}
要构建HashSet,您可以在O(n)
中执行以下操作,其中n是s1.length()
Set<Substring> substrings = new HashSet<>();
for (int i = 0; i < s1.length() - n; i++) {
Substring ss = new Substring(s1, i, n);
substrings.add(ss);
}
要搜索匹配项,您可以在O(n)
中执行以下操作,其中n是s2.length()
for (int i = 0; i < s2.length() - n; i++) {
Substring ss = new Substring(s2, i, n);
if (substrings.contains(ss))
return true; // found a match.
}
答案 1 :(得分:1)
所以,没有contains
,substring
我假设你不打算使用任何Java API。这是一个使用动态编程的实现:
public static boolean hashCheated(String a, String b, int N) {
int m = a.length();
int n = b.length();
int max = 0;
int[][] dp = new int[m][n];
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(a.charAt(i) == b.charAt(j)){
if(i==0 || j==0){
dp[i][j]=1;
}else{
dp[i][j] = dp[i-1][j-1]+1;
}
if(max < dp[i][j])
max = dp[i][j];
}
}
}
return (max >= N);
}