串模式匹配算法的几种代码实现

c语言中字符串处理的库函数还是比较全的,c++里的string类就更不用说了。有些处理函数虽然已封装为库函数,直接调用即可,但是正在学习数据结构,还是想敲些代码,以便总结+巩固。

首先,总结一下常用的c语言中字符串处理标准库函数: (仅仅是我想复习一下。。。) 

// #include<string.h>  

char* srtcpy(char* dst,const char* src);  //从src地址开始且含有'\0'结束符的字符串(c风格字符串)复制到以dst开始的地址空间. 并返回char型指针,与dst指向同                                                                                    一内容.

char* strcat(char* str1,char* str2);  // 把str2所指字符串添加到str1结尾处(覆盖str1结尾处的'\0')并添加'\0'.

int strcmp(char* str1,char* str2);  //比较字符串大小,str1>str2,返回正数,str1<str2,返回负数,str1==str2,返回0.

unsigned int strlen(char* str);  // 返回字符串长度(以第一个字符串结束符'\0'为终止).

char* strchr(const char* str,char c);  // 查找字符串中首次出现字符c的位置,成功则返回要查找字符第一次出现的位置,失败返回NULL.

char* strrchr(const char* str,char c);// 查找字符c在字符串str中末次出现的位置,返回从字符串中的这个位置起,一直到字符串结束的所有字符. 如果未能找到指定字符,那么返回NULL.

char* strdup(char* str);  // 将串拷贝到新建的位置处,在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏.

int stricmp(char* str1,char* str2);  // 比较字符串大小,对大小写不敏感.

int strnicmp(char* str1,char* str2,unsigned int n); // 比较字符串str1与str2的前n个字符,不区分大小写.

char* strnset(char* str,char c,unsigned int n);  // 将一个字符串中的前n个字符都设为指定字符c.

char* strtok(char* str,const char* delim);  // 分解字符串为一组字符串,s为要分解的字符串,delim为分隔符字符串.str为要分解的字符串,delim为分隔符字符串.首次调用时s指向要分解的字符串,之后再次调用要把s设成NULL.

char* strrev(char* str);  // 串倒转.

char* strstr(char* str1,const char* str2);  // 确定str2在str1的第一次出现的位置,返回子串在str1首位置的地址.如果str2不是str1的子串,返回NULL

char* strpbrk(const char* str1,const char* str2);  // 依次检验字符串str1中的字符,当被检验字符在字符串str2也包含时,则停止检验.并返回该字符位置,空字符null不包括在内.

size_t strcspn(const char* str1,const char* str2);  // 顺序在字符串str1中搜寻与str2中第一个的相同字符,包括结束符NULL,返回这个字符在str1中第一次出现的位置,返回在字符串str1中的下标值,即在str1中出现而str2中没有出现的子串的长度)


串模式匹配:  实现函数: unsigned int Index(const char* S,const char* T,unsigned int pos);

主函数在此:

void main()
{
	char* S="BBC ABCDAB ABCDABCDABDE";
	char* T="ABCDABD";
	printf("串T在串S中首次出现的位置是:%d\n",Index(S,T,1)); //位置值从1开始,pos>=1 && pos<=strlen(S)
}

一、依赖比较、求串长、求子串函数的实现:

char* SubString(const char* str,unsigned int pos,unsigned int len)
{
	if(str==NULL)
	{
		printf("Wrong point!\n");
		return 0;
	}
	if(pos>0 && len>0)
	{
		unsigned int i=pos,j=0;
		char temp[20]={0};
		while(i<=pos+len-1)
		{
			temp[j]=str[i-1];
			++i;++j;
		}
		return temp;
	}
	return NULL;
}

unsigned int Index(const char* S,const char* T,unsigned int pos)
{
	if(S==NULL || T==NULL)
	{
		printf("Wrong point!\n");
		return 0;
	}
	if(pos>0)
	{
		unsigned int n=strlen(S);
		unsigned int m=strlen(T);
		unsigned int i=pos;
		while(i<=n-m+1)
		{
			char* temp=SubString(S,i,m);
			if(strcmp(temp,T))
				++i;
			else
				return i;
		}
	}
	return 0;
}
执行结果:



二、不依赖其他串操作的实现:

unsigned int Index(const char* S,const char* T,unsigned int pos)
{
	if(S==NULL || T==NULL)
	{
		printf("Wrong point!\n");
		return 0;
	}
	if(pos>0)
	{
		unsigned int n=strlen(S);
		unsigned int m=strlen(T);
		unsigned int i=pos,j=1;
		while(i<=n && j<=m)
		{
			if(S[i-1]==T[j-1])
			{
				++i;++j;
			}
			else
			{
				i=i-(j-1)+1;
				j=1;
			}
		}
		if(j>m)
			return i-m;
		else
			return 0;
	}
	return 0;
}
执行结果同上.

三、采用上篇转载博文中介绍的改进算法:KMP算法

#include <iostream>
#include <string>
#include <vector>
using namespace std;

void Min(string t,vector<int>& key)
{
	string temp1; //子串前缀
	string temp2; //子串后缀
	int i=2,j=1,k,len=t.length();
	//vector<int> key;
	while(i<len) //长度为i的子串
	{
		//if(i==1)
			//key[j]=0;
		k=1;
		while(k<i) //长度为i的子串有i-1个前/后缀,同级相比较
		{
			temp1=t.substr(0,k);
			temp2=t.substr(i-k,k);
			if(temp1==temp2)
				key[j]=temp1.length();
			++k;
		}
		++j;
		++i;
	}
}

int Index(string s,string t,int pos)
{
	int i=pos-1,slen=s.length(),tlen=t.length();
	vector<int> key;
	for(int a=0;a<tlen;++a)
		key.push_back(0);
	Min(t,key);
	int j=0;
	int k=0;
	int ppos=0;
	while(1)
	{
		if(s[j]!=t[k])
		{
			if(k==0)
			{
				++j;
				++ppos;
				continue;
			}
			else
			{
				ppos+=k-key[k-1];
				j=ppos;
				k=0;
			}
		}
		else if(s[j]==t[k])
		{
			if(k==tlen-1)
				return ppos+1;
			else
			{
				++k;
				++j;
			}
		}
		if(j==slen)
			return -1;
	}
}

void main()
{
	string S("BBC ABCDAB ABCDABCDABDE");
	string T("ABCDABD");
	int v=Index(S,T,1);
	if(v>=0)
		cout<<"串T在串S中首次出现的位置是:"<<Index(S,T,1)<<endl;
	else
		cout<<"串T不是串S的子串."<<endl;
}
执行结果:


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值