in place 字符串替换--利用KMP匹配

504 篇文章 0 订阅

实现字符串替换


假设原字符串长度足够大, replaced 字符串 和 new 字符串的 长度没有限制


算法中用到了 KMP 的匹配算法


// 字符串替换2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>


/**
 * @brief CalcKMPNext 计算kmp算法需要的next数组
 *
 * @param keyword 关键字
 * @param keywordLen 关键字长度
 * @param next 存储next
 */
void CalcKMPNext(const char* keyword, const int keywordLen, char* next)
{
    int i = 0, j = -1;
    next[i] = j;//初始化next[0],没有什么意义
    while (i < keywordLen)
    {
        //如果不相等,回退直到相等,或者没有相等
        while (j >= 0 && keyword[i]!=keyword[j])
            j = next[j];
        ++i;
        ++j;
        if (i<keywordLen)
            next[i] = j;
    }
}

/**
 * @brief KMPSearch kmp搜索字符串算法
 *
 * @param src 待搜索的文本
 * @param srcLen 待搜索文本长度
 * @param keyword 搜索关键字
 * @param keywordLen 搜索关键字长度
 *
 * @return 搜索到第一个结果停止,返回关键字在文本出现的索引,否则返回-1
 */
int KMPSearch(const char* src, const char* keyword)
{
	int srcLen = strlen(src);
	int keywordLen = strlen(keyword);

    //存储kmp需要的next数组
    char* next = (char*)malloc(keywordLen*sizeof(char));
    if (!next)
        return -1;

    //初始化next数组的值
    CalcKMPNext(keyword, keywordLen, next);

    int i = 0, j = 0;
    for ( ; i<keywordLen; ++i)
        printf("next: %d\n", next[i]);
    i = 0;
    while (i < srcLen)
    {
        //如果比较结果不同,则需要回退关键字的索引,继续比较,如果回退至关键字开始处(j==0)时break,下次直接从当前i与关键字的第一个字符开始比较
        while (j >= 0 && src[i] != keyword[j])
            j = next[j];
        printf("i=%d,j=%d\n",i,j);
        i++;
        j++;
        if (j == keywordLen)
		{
			free(next);
            return i - keywordLen;
		}
    }

	free(next);
    return -1;
}



int calcStrTimes(char *Array, char *pattern)
{
	char *pCur = Array;
	int patternLen = strlen(pattern);
	int arrStrLen = strlen(Array);
	int patternPos;
	int count = 0;

	while (pCur < Array+arrStrLen)
	{
		patternPos = KMPSearch(pCur, pattern);
		if (patternPos != -1)
		{
			count++;
			pCur = pCur + patternPos + patternLen;
		}
		else
		{
			break;
		}
	}
	return count;
}


char* replace2(char *Array, char* oldStr, char* newStr)
{
	if (Array == NULL || Array[0] == '\0')
		return NULL;

	if (oldStr == NULL || oldStr[0] == '\0')
		return Array;

	if (newStr == NULL || newStr[0] == '\0')
		return Array;

	int oldStrLen = strlen(oldStr);
	int newStrLen = strlen(newStr);
	int arrStrLen = strlen(Array);

	bool bSiftFlag = newStrLen > oldStrLen? true:false;

	char *pCur;
	char *pNew;
	int  siftDistance = 0;

	if (!bSiftFlag)
	{
		pCur = Array;
	}
	else
	{
		siftDistance = calcStrTimes(Array, oldStr) * (newStrLen - oldStrLen);
		for (int idx = arrStrLen - 1; idx >=0; idx--)
		{
			Array[idx+siftDistance] = Array[idx];
		}
		pCur = Array + siftDistance;
	}

	pNew = Array;


	int oldStrPos = KMPSearch(pCur, oldStr);
	while (pCur < &Array[0]+arrStrLen+siftDistance)
	{
		if (oldStrPos != -1)
		{
			char *pDestPos = pCur + oldStrPos;
			while(pCur < pDestPos)
			{
				*pNew++ = *pCur++;
			}
			
			memcpy(pNew, newStr, newStrLen);

			pCur += oldStrLen;
			pNew += newStrLen;

			oldStrPos = KMPSearch(pCur, oldStr);
		}
		else
		{
			*pNew++ = *pCur++;
		}
	}
	*pNew = '\0';

	return Array;
}


int _tmain(int argc, _TCHAR* argv[])
{
	char A[100] = {'\0'};

	memcpy(A, "abcdef345kdgfaxyzfereaxyzeewaxyzdf", 34);

	printf("%s\n", A);

	replace2(A, "xyz", "CCIC");

	printf("%s\n", A);

	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值