String Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1653 Accepted Submission(s): 747
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
abcder aaaaaa ababab
1 1 6 1 1 6 1 6 1 3 2 3
此题可用最小(大)表示法求出first和last string,用kmp的next数组求出最小循环节,这出现次数为len/最小循环节,f此题irst出现次数和last出现次数相等。
可以看一下kmp算法:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html
kmp求最小循环节:http://blog.sina.com.cn/s/blog_7981299401012xl0.html
最小表示法:http://blog.csdn.net/cclsoft/article/details/5467743
代码示例:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define maxh 10000000+100
using namespace std;
char str[maxh+maxh],strs[maxh];
int next[maxh];
int minsign(int m)
{
int i,j,l;
i=0,j=1;
while(i<m&&j<m)
{
for(l=0;l<m;l++)
if(str[(i+l)%m]!=str[(j+l)%m])break;
if(l>m)break;
if(str[(i+l)%m]>str[(j+l)%m])
i=i+l+1;
else
j=j+l+1;
if(i==j)j=i+1;
}
if(i<j)return i;
return j;
}
int maxsign(int m)
{
int i,j,l;
i=0; j=1;
while(i<m&&j<m)
{
for(l=0;l<m;l++)
if(str[(i+l)%m]!=str[(j+l)%m]) break;
if(l>m) break;
if(str[(i+l)%m]<str[(j+l)%m])
i=i+l+1;
else
j=j+l+1;
if(i==j) j=i+1;
}
if(i<j) return i;
return j;
}
void bmf(int m)
{
int i=0,j=-1;
next[0]=-1;
while(i<m)
{
if(j==-1||str[i]==str[j])
{
i++;
j++;
next[i]=j;
}
else
{
j=next[j];
}
}
}
int main()
{
while(~scanf("%s",str))
{
int L=strlen(str);
int l1=minsign(L);
int l2=maxsign(L);
bmf(L);
int l=L-next[L];
int ans=L%l?1:L/l;
printf("%d %d %d %d\n",l1+1,ans,l2+1,ans);
}
return 0;
}