为什么我要做这么水的题呢,因为我实在是太弱了- -
刚补完数学(水了好多题的样子)于是就来水字符串了,感觉自己这方面的数据结构的知识好少。
只好从KMP开始水了。
于是就看到了这道最小最大表示法+KMP的题。
以前总感觉最小表示法好高端的样子
现在才发现
卧槽真简单啊
要不要这么简单啊
就是搞两个指针,i在前,j在后,以及当前已匹配的长度k,
如果s[i+k]==s[j+k],那么显然k++。
如果s[i+k]>s[j+k],那么可以发现s[i],s[i+1]......s[i+k]都不是最小表示了,所以i->i+k+1。
同理s[i+k]<s[j+k]的时候j->j+k+1。
于是就求完了,复杂度O(N)。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000005];
int fail[1000005],n;
void getfail(){
int j=0;
for(int i=2;i<=n;i++){
while(j&&s[j+1]!=s[i])j=fail[j];
if(s[j+1]==s[i])j++;
fail[i]=j;
}
}
int express(bool flag){
int i=1,j=2,k=0;
while(i<=n&&j<=n&&k<=n){
int tmp=s[(i+k-1)%n+1]-s[(j+k-1)%n+1];
if(!tmp)k++;
else{
if(flag){
if(tmp<0)j+=k+1;
else i+=k+1;
}else{
if(tmp<0)i+=k+1;
else j+=k+1;
}
k=0;
if(i==j)j++;
}
}
return min(i,j);
}
int main(){
while(scanf("%s",s+1)==1){
n=strlen(s+1);
getfail();
int ans=n-fail[n];
ans=n%ans?1:n/ans;
printf("%d %d %d %d\n",express(true),ans,express(false),ans);
}
return 0;
}