求串的第一个最长重复子串的下标和长度

/*
采用顺序结构存储串,编写一个程序,求串s中出现的第一个最长重复子串的下标和长度。


1.读取串
2.求后缀数组
3.字典序排序所有后缀
4.求相邻后缀最长子串
5.比较本次结果与上次结果,取最大
*/


#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<fstream>


using namespace std;


typedef vector<string>::iterator ITER;//从定义类型


class max_substr
{
public:
max_substr(){}


~max_substr(){}

//文件读入串
void getstr(string name)
{
ifstream readfile;
readfile.open(name, ios::in);
if (readfile.is_open())//是否打开
{
getline(readfile, s);//读取一行
cout << s << endl;
}
readfile.close();
}


void solve()
{
int temp, max;
string t, max_t;


//得到后缀数组
for (size_t i = 0; i<s.size(); ++i)
{
t = s.substr(i, s.size());//求后缀
behind.push_back(t);
rank.insert(pair<string, int>(t, i));//存储后缀及其首字符下标
}
stable_sort(behind.begin(), behind.end());//按字典序排序,默认为从小到大
max = -1;
//迭代比较相邻两后缀
for (iter = behind.begin(); *iter != behind.back(); ++iter)
{
temp = MaxPrefix(iter, iter + 1);//取最长子串尾字符下标
if (temp>max)//与前一个比较,取最长
{
max = temp;
max_i = iter;
}
}


for (int i = 0; i<max; ++i)//取出重复串
max_t += (*max_i)[i];
cout << "长度为:" << max << endl;
cout << "下标为:" << rank[max_t] << endl;
cout << max_t << endl;
}


private:
string s;
vector<string> behind;//后缀数组
map<string, int> rank;//关联容器
ITER iter, max_i;//迭代/保存字符地址位置


//得到相邻两串最长公共字符子串尾下标
int MaxPrefix(ITER s1, ITER s2)
{
int i = 0;
while (!(*s1).empty() && (*s1)[i] == (*s2)[i])//当前字符相等比较下一位
{
++i;
}
return i;
}
};


int main()
{
max_substr str;
str.getstr("data");
str.solve();
return 0;
}


测试结果



最长重复子串(Longest Repeated Substring)问题是指在一个字符找到重复出现次数最多的子串,并返回该子串以及它的起始下标。这个问题通常可以用滑动窗口(Sliding Window)的数据结构和动态规划(Dynamic Programming)的思想来解决。 下面是Python的一个简单实现: ```python def longest_repeated_substring(s): if not s: return "", -1 length = len(s) # 使用两个哈希集合存储当前和前一窗口内的字符 window_set, prev_window_set = set(), set() max_len = 1 start = 0 for i in range(length): # 如果当前字符已经在前一个窗口内,则说明找到了重复子串 if s[i] in prev_window_set: # 更新最大长度和起点 cur_len = i - prev_window_set[s[i]] if cur_len > max_len: max_len = cur_len start = prev_window_set[s[i]] + 1 # 将当前字符添加到窗口集合,移除窗口左侧已超出部分 prev_window_set.remove(s[start]) window_set.add(s[i]) # 如果窗口右侧有新的字符,将其添加到窗口集合 if i >= max_len: prev_window_set.add(s[start]) # 返回最长重复子串和起始下标 return s[start:start+max_len], start # 测试例子 s = "banana" sub, index = longest_repeated_substring(s) print(f"最长重复子串是 '{sub}',位于索引 {index}") ``` 在这个代码,我们用一个滑动窗口从左到右遍历输入字符`s`。窗口内的每个字符都在一个集合维护,当遇到重复字符时,就更新最长重复子串长度和起始位置。如果窗口移动过程有新的字符加入,我们就移除窗口左侧的第一个字符。这样做的目的是保持窗口内字符的独特性,从而快速查找重复字符。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值