字符串交错组成
对于三个字符串A,B,C。我们称C由A和B交错组成当且仅当C包含且仅包含A,B中所有字符,且对应的顺序不改变。请编写一个高效算法,判断C串是否由A和B交错组成。
给定三个字符串A,B和C,及他们的长度。请返回一个bool值,代表C是否由A和B交错组成。保证三个串的长度均小于等于100。
测试样例:
“ABC”,3,”12C”,3,”A12BCC”,6
返回:true
动态规划分析
dp[i][j] 表示 A[0…i-1] , B[0…j-1] 能否构成 C[0…i+j-1]
相当于字符串前面加了空字符
dp[0][0] = true;
dp[0][j] 就是比较B与C
dp[i][0] 就是比较A与Cdp[i][j] 与 dp[i][j-1] B[j-1]
和 dp[i-1][j] A[i-1] 相关
只要其中有一个满足 dp[i][j] 就是满足的
ac代码
class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
// write code here
if (n + m != v)
return false;
vector<vector<bool>> dp(n + 1, vector<bool>(m + 1,false));
dp[0][0] = true;
int j = 1;
while (j <= m)
{
if (dp[0][j-1] == false)
break;
if (B[j - 1] == C[j - 1])
dp[0][j] = true;
j++;
}
int i = 1;
while (i <= n)
{
if (dp[i-1][0] == false)
break;
if (A[i - 1] == C[i - 1])
dp[i][0] = true;
i++;
}
for (i = 1; i <= n; i++)
{
for ( j = 1; j <= m; j++)
{
if (dp[i][j - 1] && B[j - 1] == C[i + j - 1])
{
dp[i][j] = true;
continue;
}
if (dp[i-1][j] && A[i - 1] == C[i + j - 1])
{
dp[i][j] = true;
continue;
}
}
}
return dp[n][m];
}// end func
};
ac代码 动态规划 空间压缩
时间复杂度仍然为O(n*m) ,空间复杂度是 O(min(n,m))
class Mixture {
public:
bool chkMixture(string A, int n, string B, int m, string C, int v) {
// write code here
if (n + m != v)
return false;
//动态规划,空间压缩,取m,n最小值
if (n > m)
{
swap(n, m);
swap(A, B);
}
vector<bool> dp(n + 1, false);
// 求第一列的值
dp[0] = true;
int i = 1;
while (i <= n)
{
if (dp[i - 1] == false)
break;
if (A[i - 1] == C[i - 1])
dp[i] = true;
i++;
}
//依次求后面的每一列,并保存到dp中
for (int j = 1; j <= m; j++)
{
for (i = 0; i <= n; i++)
{
// 第一行 只看左边,后面的每行 都看上面和左边
if (i != 0)
{
if (dp[i - 1] && A[i - 1] == C[i + j - 1])//上面 就上刚刚求的 dp[i-1]
{
dp[i] = true;
continue;
}
}
if (dp[i] && B[j - 1] == C[i + j - 1])//左边 就是dp[i]
{
dp[i] = true;
continue;
}
dp[i] = false;
}
}
return dp[n];
}// end func
};
串的模式匹配
对于两个字符串A,B。请设计一个高效算法,找到B在A中第一次出现的起始位置。若B未在A中出现,则返回-1。
给定两个字符串A和B,及它们的长度lena和lenb,请返回题目所求的答案。
测试样例:
“acbc”,4,”bc”,2
返回:2
ac代码1
class StringPattern {
public:
int findAppearance(string A, int lena, string B, int lenb) {
// write code here
if (lena <= 0 || lenb <= 0)
return -1;
if (lenb > lena)
return -1;
if (lenb == lena)
{
return (A == B) ? 0 : -1;
}
vector<int> dp(lenb + 1);
for (int i = 1; i <= lenb; i++)
dp[i] = 0;
for (int j = 1; j <= lena; j++)
{
vector<int> tmp(dp);
for (int i = 1; i <= lenb; i++)
{
if (B[i - 1] == A[j - 1])
{
tmp[i] = dp[i - 1] + 1;
if (tmp[i] == lenb)
return (j - 1 - lenb + 1); //cout << j -1 - lenb + 1 << endl;
}
else{
tmp[i] = 0;
}
}
dp.assign(tmp.begin(), tmp.end());
}
return -1;
}
};
KMP算法模式匹配
class StringPattern {
public:
vector<int> getNextArray(string s, int n)
{
if (n == 1)
{
vector<int> next{ -1 };
return next;
}
vector<int> next(n);
next[0] = -1;
next[1] = 0;
int pos = 2;
int cn = 0;
while (pos < n)
{
if (s[pos - 1] == s[cn])
{
next[pos++] = ++cn;
}
else if (cn > 0)
{
cn = next[cn]; // cn > next[cn],此步是回跳到前面的位置
}
else{
next[pos++] = 0;
}
}
return next;
}
int findAppearance(string A, int lena, string B, int lenb) {
// write code here
if (lena <= 0 || lenb <= 0)
return -1;
if (lenb > lena)
return -1;
if (lenb == lena)
{
return (A == B) ? 0 : -1;
}
vector<int> next = getNextArray(B, lenb);
int i = 0;
int j = 0;
while (i < lena && j < lenb)
{
if (A[i] == B[j])
{
i++;
j++;
}
else{
if (next[j] == -1){
i++;
j = 0;
}
else{
j = next[j];
}
}
}
if (j == lenb){
return i - j;
}
return -1;
}
};
next数组中, next[i] 表示 str[0到i-1]中,前缀和后缀相等的最大值
具体求解时
pos 表示遍历到的位置
cn 表示 next[i-1] 匹配是到cn不满足了(即 str[0,cn-1]与 str[…, i-2]是匹配的)
KMP中 使用next的两种情况,对j和i回溯
https://leetcode.com/problems/implement-strstr/
ac代码
class Solution {
public:
vector<int> getNextArray(string s, int n)
{
if (n == 1)
{
vector<int> next{ -1 };
return next;
}
vector<int> next(n);
next[0] = -1;
next[1] = 0;
int pos = 2;
int cn = 0;
while (pos < n)
{
if (s[pos - 1] == s[cn])
{
next[pos++] = ++cn;
}
else if (cn > 0)
{
cn = next[cn]; // cn > next[cn],此步是回跳到前面的位置
}
else{
next[pos++] = 0;
}
}
return next;
}
int findAppearance(string A, int lena, string B, int lenb) {
if (lena >= 0 && lenb == 0)
return 0;
if (lena == 0 && lenb > 0)
return -1;
if (lenb > lena)
return -1;
if (lenb == lena)
{
return (A == B) ? 0 : -1;
}
vector<int> next = getNextArray(B, lenb);
int i = 0;
int j = 0;
while (i < lena && j < lenb)
{
if (A[i] == B[j])
{
i++;
j++;
}
else{
if (next[j] == -1){
i++;
j = 0;
}
else{
j = next[j];
}
}
}
if (j == lenb){
return i - j;
}
return -1;
}
int strStr(string haystack, string needle) {
int len1 = haystack.size();
int len2 = needle.size();
return findAppearance(haystack, len1, needle, len2);
}
};