就是dp,从后面开始dp,题意是不能有连续的相同的字符串,开始读错题了,从右往左推,设valid[i]表示存不存在一种方案,使得能将s[i](包括)以后的字符全部拿掉,这个就可以递推了,每往左推一格,看valid[i+2]和valid[i+3],如果为真,再往后搜一下相应的字符串,看有没有连续出现。要注意的是,就算连续出现了,如果存在一种方案使得长度不一样的话,也是合法的,例如pptpptt,搜ppt的时候,是连续出现的,但可以这么分:ppt|pp|tt,所以需要额外判断下valid[i+5]。一旦合法,就把valid[i]置为1,以此类推。但有一个问题,为什么val[5]为真就一定可以,有可能紧跟的字符串不一定就可以按照其理想的长度啊?没想明白
1 #include <cstdio>
2 #include <cstring>
3 #include <set>
4 #include <iostream>
5 #include <map>
6 #include <math.h>
7 #include <algorithm>
8 using namespace std;
9 typedef long long ll;
10 const int N = 1000005;
11 const double pi= 3.14159265358979323846264;
12 bool val[10009];
13 set<string>ans;
14
15 int main()
16 {
17 //freopen("in.txt","r",stdin);
18 string s;
19 cin>>s;
20 int l=s.length();
21 val[l]=true;
22 for(int i=l-1;i>4;i--){
23 if(val[i+2]){
24 string t=s.substr(i,2);//直接求子串
25 if(s.find(t,i+2)!=i+2||val[i+5]){//find表示从i+2位置开始找第一个与t相等字符串的位置
26 val[i]=true;
27 ans.insert(t);
28 }
29 }
30 if(val[i+3]){
31 string t=s.substr(i,3);
32 if(s.find(t,i+3)!=i+3||val[i+5]){
33 val[i]=true;
34 ans.insert(t);
35 }
36 }
37
38 }
39 cout<<ans.size()<<endl;
40 set<string>::iterator it;//set是自动去重并安字典序排序orz高大上,输出方式也高大上
41 for( it=ans.begin();it!=ans.end();it++)
42 cout<<it->c_str()<<endl;
43
44 return 0;
45 }