题意:给定字符串,前缀大于4,后缀只能为2或3,并且连续两个后缀不重复,找到所有可能后缀并输出
思路
想吧,是dp问题
如何得知是dp问题? 分析得到,每个字符串能否是后缀与其后字符串的状态有关,可以归为地推问题,而递推是dp的特例
一个串能否是后缀之一,取决于两点
- 其前面是否能作为前缀
- 其后面是否能作为后缀并且与它连续重复
- 是否能作为前缀 能作为前缀,则第一个后缀就是当前字符串,并且长度大于4
- 是否后缀
- 要构成后缀,首先得其自身满足串可以有数个后缀组成
- 并且该串后面的串不可以与其相同:
- 若是相同,则看取另一个长度,一定不同
- 而另一长度这种取法是否成立,取决于取另一长度后,其后是否能够成后缀串
由此写出代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;
const int N = 1e5 + 10;
bool f[N];
int main()
{
string s;
cin >> s;
int n = s.size();
//cout << n;
set<string> ans;
f[n-1] = true;
for(int i = n - 2; i >= 4; i --)
for(int j = 2; j <= 3; j ++)
{
if(f[i + j])
{
//判断是否当前串与之后的同长度的串是否相同
string t1 = s.substr(i + 1, j);
string t2 = s.substr(i + j + 1, j);
if(t1 != t2 || f[i + 5])
{
//可以作为后缀
ans.insert(t1);
f[i] = true;
}
}
}
cout << ans.size() << endl;
//set自动按照字典序排序
for(auto& t : ans)
cout << t << endl;
return 0;
}
分析问题多动笔,分类讨论化繁为简 如果分析到递推关系,就分类找递推式,考虑边界情况后按递推式实现代码