循环节
时间限制: 1 Sec 内存限制: 64 MB
提交: 56 解决: 16
[提交][状态][讨论版]
题目描述
第一节是英语课。今天,老师又教了桐桐很多单词。桐桐发现所有单词都有循环节(大写字母一律化成小写字母)。如a(循环长度为1,循环节为
a),luLul(循环长度为2,循环节为lu),OlyMPic(循环长度为7,循环节为olympic),CcCcccc(循环长度为1,循环节为
c),等等。
而且,桐桐发现这能加速她背单词。她上课和ROBIN说了话,老师罚她背单词。虽然就一个,但长度实在太大,单词大小写可以不管,求桐桐需要记多长的最小循环节,并把这个单词的最小循环节输出来(最后一个循环节可以没完)。
输入
1行,是一个单词,其中不一定只出现小写字母,并且长度小于101000。
输出
2行,第1行输出循环长度,第2行输出循环节(全部输出小写字母)。
样例输入
erEreR
OlyMpic
样例输出
2
er
7
olympic
提示
30%的数据满足:字符串长度≤255,字符串中均为小写字母;
50%的数据满足:字符串长度≤255,字符串中不一定只出现小写字母;
70%的数据满足:字符串长度≤10000,字符串中不一定只出现小写字母:
100%的数据满足:字符串长度≤101000,字符串中不一定只出现小写字母
【分析】考虑到循环节一定是以第一个字符开头的,那我们把所有str[0]出现的位置记录s[]下来,然后将0--(s[i]-1)的子字符串放入队列搜索,率先搜到的一定是字典序最小的。
如果一直搜不到,那就是他本身咯。
#include <iostream> #include <cstring> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <time.h> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define inf 0x3f3f3f3f #define mod 1000000007 typedef long long ll; using namespace std; const int N=101005; double m=1e7; int s[N]; bool tt; string str; int n; struct man { string str; int num; }; bool check(string a,string b) { for(int i=0; i<a.size(); i++) { if(b[i]!=a[i])return false; } return true; } queue<man>q; void bfs() { while(!q.empty()) { man t=q.front(); q.pop(); int nn=t.str.size(); string ss=str.substr(t.num,nn); if(nn+t.num>n) { if(check(ss,t.str)) { tt=true; printf("%d ",nn); cout<<t.str<<endl;return; } } else { if(ss==t.str){man k=t;k.num+=nn;q.push(k);} } } } int main() { while(cin>>str) { memset(s,0,sizeof(s)); int cnt=0;tt=false; n=str.size(); bool flag=false; for(int i=0; i<str.size(); i++) { if(str[i]<97)str[i]+=32; if(str[i]==str[0])s[cnt++]=i; if(str[i]!=str[0])flag=true; } if(!flag) { cout<<"1"<<endl<<str[0]<<endl; } else { for(int i=1; i<cnt; i++) { string g=str.substr(0,s[i]); man G; G.num=s[i]; G.str=g; q.push(G); bfs(); if(tt)break; } } if(!tt)cout<<n<<endl<<str<<endl; } return 0; }