求最长重复子串--算法与数据结构课程作业

暴力破解–最长重复子串


本文知识点(你可能会学到):

  1. 求子串算法
  2. BF字符串匹配算法(进阶KMP算法更好)
  3. 字符串中的所有子串进行遍历

1. 求子串算法

//求子串
int seekSubString(string* sub,string* s,int start,int sub_len,int s_len)//子串,主串,子串开始位置,子串长度,主串长度
{
	//若0<=start<=length(s)-1且0<=len<=length(s)-start+1,则返回一个
	//从第start个字符起,长度为len的连续字符序列,否则返回一个FALSE
	int i;
	if ((start >= 0 && start < s_len ) && (sub_len >= 0 && sub_len <= s_len - start))
	{
		for (i = 0; i < sub_len; i++)
		{
			sub->ch[i] = s->ch[start + i];
			sub->length = sub_len;
		}
		return TRUE;//操作成功
	}
	else
	{
		sub->length = -1;
		return FALSE;//操作失败,无法找到该子串
	}
}

2.BF算法(串的模式匹配算法)

模式匹配概念: 设有两个串S和P,如果P是S的子串,则将查找P在S中出现的位置的操作过程称为模式匹配!

//串的模式匹配算法-----BF
int Index_BF(string* s, string* t,int Pos)
{
	//Brute-Force算法思想 求模式串t在主串s中的定位函数 
	int i = Pos, j = 0;
	while ((i < s->length) && (j < t->length))
	{
		if (s->ch[i] == t->ch[j])//如果有字符相等的地方,执行下面语句
		{
			i = i + 1;//继续比较后继字符
			j = j + 1;
		}
		else
		{
			i = i - j + 1;
			j = 0;//重新开始匹配模式串
		}
	}
	if (j >= t->length)//判断完毕
	{
		//return i - t->length + 1;
		return i - t->length;//返回数组下标
	}
	else
	{
		return -1;
	}
}

3.求最长重复子串(遍历)

//求串中最长重复子串abcdabcdabgh
int find_the_longest_repeated_substring(char* String,int s_len)
{
	//初始化字符串
	string* sub = (string*)malloc(sizeof(string));
	if (sub == NULL) return -1;
	string* s = (string*)malloc(sizeof(string));
	if (s == NULL) return -2;

	strcpy(s->ch, String);//主串
	s->length = s_len;
	for (subLen = 2; subLen <= strlen(String); subLen++)
	{
		for (SubIndex = 0; SubIndex < strlen(String) - subLen + 1; SubIndex++)
		{
			int ret = seekSubString(sub, s, SubIndex, subLen,strlen(String));
			if (ret == TRUE)
			{
				if (SubIndex + 1 >= strlen(String)) break;
				int retIndex = Index_BF(s,sub,SubIndex+1);
				if (retIndex != -1)
				{//表示返回数组下标成功,找到重复子串
					if (maxSubstringLen < subLen)
					{
						maxSubstringLen = subLen;//将该子串的长度赋值给最长子串长度
						maxStringIndex = retIndex;//将返回的下标赋值给maxStringIndex
					}
				}
			}
		}
	}
	if (maxSubstringLen > 1)
	{
		//打印出最长重复子串
		int j = 0;
		for (int i = maxStringIndex; j < maxSubstringLen; i++,j++)
		{
			printf("%c", sub->ch[i]);
		}
		puts("");
		return TRUE;
	}
	return FALSE;
}

完整代码

//创作内容:求串中最长重复子串
//例子:abcdabcdabgh(例子)返回值:abcdab
// 创作时间:2021-10-09
// 更新时间:2021-10-20
// 创作作者:辰梦star_dream
//
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>//标准输入输出头文件
#include<string.h>
#include<stdlib.h>

//允许的最大字符数量
#define MAXNUM 1000
#define TRUE 1
#define FALSE -1

//全局变量
int SubIndex = 0;//重复子串开头下标
int subLen = 2;//子串长度从2开始,因为0和1不算重复子串
int maxSubstringLen = 1;//最长子串的字符长度
int maxStringIndex = 0;//最长字符串的下标

typedef struct Stringsub
{
	char ch[MAXNUM];//定义字符串
	int length;//字符串长度
}string;

//求子串
int seekSubString(string* sub,string* s,int start,int sub_len,int s_len)//子串,主串,子串开始位置,子串长度,主串长度
{
	//若0<=start<=length(s)-1且0<=len<=length(s)-start+1,则返回一个
	//从第start个字符起,长度为len的连续字符序列,否则返回一个FALSE
	int i;
	if ((start >= 0 && start < s_len ) && (sub_len >= 0 && sub_len <= s_len - start))
	{
		for (i = 0; i < sub_len; i++)
		{
			sub->ch[i] = s->ch[start + i];
			sub->length = sub_len;
		}
		return TRUE;//操作成功
	}
	else
	{
		sub->length = -1;
		return FALSE;//操作失败,无法找到该子串
	}
}

//串的模式匹配算法-----BF
int Index_BF(string* s, string* t,int Pos)
{
	//Brute-Force算法思想 求模式串t在主串s中的定位函数 
	int i = Pos, j = 0;
	while ((i < s->length) && (j < t->length))
	{
		if (s->ch[i] == t->ch[j])//如果有字符相等的地方,执行下面语句
		{
			i = i + 1;//继续比较后继字符
			j = j + 1;
		}
		else
		{
			i = i - j + 1;
			j = 0;//重新开始匹配模式串
		}
	}
	if (j >= t->length)//判断完毕
	{
		//return i - t->length + 1;
		return i - t->length;//返回数组下标
	}
	else
	{
		return -1;
	}
}

//求串中最长重复子串abcdabcdabgh
int find_the_longest_repeated_substring(char* String,int s_len)
{
	//初始化字符串
	string* sub = (string*)malloc(sizeof(string));
	if (sub == NULL) return -1;
	string* s = (string*)malloc(sizeof(string));
	if (s == NULL) return -2;

	strcpy(s->ch, String);//主串
	s->length = s_len;
	for (subLen = 2; subLen <= strlen(String); subLen++)
	{
		for (SubIndex = 0; SubIndex < strlen(String) - subLen + 1; SubIndex++)
		{
			int ret = seekSubString(sub, s, SubIndex, subLen,strlen(String));
			if (ret == TRUE)
			{
				if (SubIndex + 1 >= strlen(String)) break;
				int retIndex = Index_BF(s,sub,SubIndex+1);
				if (retIndex != -1)
				{//表示返回数组下标成功,找到重复子串
					if (maxSubstringLen < subLen)
					{
						maxSubstringLen = subLen;//将该子串的长度赋值给最长子串长度
						maxStringIndex = retIndex;//将返回的下标赋值给maxStringIndex
					}
				}
			}
		}
	}
	if (maxSubstringLen > 1)
	{
		//打印出最长重复子串
		int j = 0;
		for (int i = maxStringIndex; j < maxSubstringLen; i++,j++)
		{
			printf("%c", sub->ch[i]);
		}
		puts("");
		return TRUE;
	}
	return FALSE;
}

int main()
{
	//求串中最长重复子串算法
	//char str[1024] = "abcdabcdabgh";
	//char str[1024] = "ababcabcacbab";
	char str[1024] = "我啊啊我暗暗我啊啊";
	int ret = find_the_longest_repeated_substring(str,strlen(str));
	if (ret == TRUE) printf("已找到最长重复子串,长度为:%d\n",maxSubstringLen);
	else if (ret == FALSE)
	{
		printf("未找到重复子串!\n");
	}
	return 0;
}

end

posted @ 2021-10-23 16:39  辰梦starDream  阅读(4)  评论(0编辑  收藏  举报  来源