暴力破解–最长重复子串
本文知识点(你可能会学到):
- 求子串算法
- BF字符串匹配算法(进阶KMP算法更好)
- 字符串中的所有子串进行遍历
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;
}