一、求最长公共子序列(LCS)
问题
求解
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int len1 = text1.length(), len2 = text2.length();
int[][] dp = new int[len1+1][len2+1];
text1 = " "+text1;
text2 = " "+text2;
char[] c1 = text1.toCharArray();
char[] c2 = text2.toCharArray();
//初始化数组,减少边界判断
for(int i=0;i<=len1;i++){
Arrays.fill(dp[i],0);
}
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(c1[i] == c2[j]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[len1][len2];
}
}
二、重复叠加字符串匹配
问题
求解
解法一:kmp
class Solution {
public:
int repeatedStringMatch(string a, string b) {
int res = 0;
string s = "";
while(s.size()<b.size()){
res++;
s+=a;
}
//此时s的长度大于b
s+=a;
int idx = kmp(s,b);
if(idx==-1) return -1;
return idx+b.size()>a.size()*res?res+1:res;
}
int kmp(string s,string p){
//在s里面找b
if(p.size()==0) return 0;
int n = s.size(), m = p.size();
s = " " + s;
p = " " + p;
int ne[m+1];
memset(ne,0,sizeof ne);
//求next数组
for(int i=2,j=0;i<=m;i++){
while(j>0 && p[i]!=p[j+1]) j = ne[j];
if(p[i]==p[j+1]) j++;
ne[i] = j;
}
//匹配
for(int i=1,j=0;i<=n;i++){
while(j>0 && s[i]!=p[j+1]) j = ne[j];
if(s[i]==p[j+1]) j++;
if(j==m){
//说明匹配成功
return i-m;
}
}
return -1;
}
};
解法二:字符串哈希
class Solution {
public:
int repeatedStringMatch(string a, string b) {
int res = 0;
string s = "";
while(s.size() < b.size()){
res++;
s+=a;
}
s+=a;//上界
int idx = strHash(s,b);
if(idx == -1) return -1;
return idx+b.size()>a.size()*res?res+1:res;
}
int strHash(string s,string b){
int P = 131;
int n = s.size(), m = b.size();
string ss = s+b;
int len = n+m;
unsigned long long h[len+10],p[len+10];
memset(h,0,sizeof h);
memset(p,0,sizeof p);
h[0] = 0;
p[0] = 1;
for(int i=0;i<len;i++){
p[i+1] = p[i]*P;
h[i+1] = h[i]*P + ss[i];
}
int r = len,l = r-m+1;
unsigned long long target = h[r]-h[l-1]*p[r-l+1];//b的哈希值
for(int i=1;i<=n;i++){
int j = i+m-1;//取b的长度
unsigned long long cur = h[j]-h[i-1]*p[j-i+1];
if(cur == target) return i-1;
}
return -1;
}
};