這是我在面試過程中遇到的一道代碼算法題,需要我在一定的時間內完成這個題目,題目的描述:
將某字符串str1中的字符串str2,全部替換成字符串str3。
例如:str1=”abcecbbccefgxyzbcgbcg”,
str2=”bc”,
str3=”xy”.
替換後爲”axyecbxycefgxyzxygxyg”
請儘可能考慮各類情況,並保證時間複雜度和空間複雜度最優。
這個題看似簡單的做法是可以的解決的,我當時也想過簡單的暴力求解法解決。後來我仔細想了想,這個題目應該分爲三步:
1找,2定,3換。先找到服藥要求的串,找出它的下標,替換該字符串。
我們都知道字符串的查找算法中最有名的就是KMP算法了,所以我決定採用KMP算法去找,找到下標後就可以替換了。若是不懂KMP算法的話,我建議大家去七月的博客上看一下他寫的詳解KMP算法,寫的很詳細很清晰很容易上手。我這裏主要是解決這個題,先就不說KMP算法的原理和部件了。我們主要討論解題的方法,下面我就給出代碼,可能並不是最優的解法,大家若有更好的解法記得跟我交流一下,一起分享一下。
//構造next 數組
void makeNext(const char *patten,int *arr)
{
assert(patten);
int len = strlen(patten);
int pos1 = 1;
int pos2 = 0;
for(inti = 1; i<len; i++)
{
if(pos1 <= i && patten[pos1-1] == patten[pos2])
{
arr[i]=arr[i-1]+1; //若前面已經出現了前綴後綴匹配,則 next 值加一 pos2++;
}
else
{
if(patten[pos1-1]==patten[0])//前面的匹配失敗,可能存在新的前綴後綴匹配
{
arr[i]=1;
pos2=1;
}
}
++pos1;
}
for(inti = len-1; i>0; --i)
{
arr[i]=arr[i]-1;
}
arr[0]=-1;
}
//將配位位置的模式串替換成新串
void Replace(char *str,const char *newstr,int plen)
{
assert(str);
assert(newstr);
for(inti = 0; i < plen; ++i)
{
str[i] = newstr[i];
}
}
//查找匹配的串的位置
int Find(const char *str,const char *patten,int len,const int *next)
{
assert(str);
assert(patten);
assert(next);
intslen = strlen(str); //主串長度
if(slen == 1) //長度爲 1 的字符串,相當於查找單個字符
{
for(int i = 0; i < len; ++i)
{
if(str[i] == patten[0])
return i;
}
return-1;
}
int s = 0; // 主串下標
int t = 0; // 子串下標
while(t<len && s<slen)
{
if(str[s] == patten[t])
{
if(t == len-1)//成功匹配
{
return(s-t);
}
++s;
++t;
}
else//不相等
{
if(next[t] == -1) //第一個都不匹配,子串與主串失敗的下一個位置比較
{
++s;
t = 0;
continue;
}
t = next[t]; //前面的已經匹配,不用再比較了
}
}
return -1;
}
void ReplaceSubstr(char *str,const char *patten,const char *newstr)
{ /* 目標:將 str中所有的 patten 串換成 newstr 串 */
//判斷指針是否合法
assert(str);
assert(patten);
assert(newstr);
assert(strlen(patten) == strlen(newstr));
//構造 next 數組
int plen = strlen(patten);//patten串的長度
int *next = newint[plen];
memset(next,0,sizeof(int)*plen);
makeNext(patten,next);
int slen = strlen(str);//主串的長度 char*pstr=str; //pstr 要不斷往前移動
int curpos = 0;//本次的相對偏移
while( (curpos = Find(pstr,patten,plen,next) ) != -1)
{
Replace(pstr+curpos,newstr,plen);
curpos += plen;
pstr += curpos;
}
delete[]next;
}
//測試用例
void TestReplacestr()
{ /*charstr[]="abcecbbccefgxyzbcgbcg"; char*patten="bc"; char*newstr="xy";*/
charstr[] = "abcecbbccefgxyzbcgb";
char*patten = "b";
char*newstr = "x";
cout<<str<<endl;
ReplaceSubstr(str,patten,newstr);
cout<<str<<endl;
}
大家若是覺得有什麼不妥的地方,請你們給我指出!