时间限制:
1000ms
内存限制:
65536kB
描述
馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到一些很奇葩的词汇。在比方说“johnsonjohnson”、“duckduck”,这些词汇虽然看起来是一些词汇的单纯重复,但是往往都是一些特殊品牌的词汇,不能被拆分开。为了侦测出这种词的存在,你今天需要完成我给出的这个任务——“找出用户请求中循环节最多的子串”。
输入
输入数据包括多组,每组为一个全部由小写字母组成的不含空格的用户请求(字符串),占一行。用户请求的长度不大于100,000。
最后一行输入为#,作为结束的标志。
输出
对于每组输入,先输出这个组的编号(第n组就是输出“Case n:”);然后输出这组用户请求中循环节最多的子串。如果一个用户请求中有两个循环节数相同的子串,请选择那个字典序最小的。
样例输入
ilovejohnsonjohnsonverymuch
duckduckgo
aaabbbcccisagoodcompany
#
样例输出
Case 1: johnsonjohnson
Case 2: duckduck
Case 3: aaa
#include<math.h>
#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=100010;
const int inf=5000000;
int w[maxn],wa[maxn],wb[maxn],wv[maxn];
int sa[maxn],rank[maxn],height[maxn];
int a[maxn],f[maxn][20],n,ft[maxn],len[maxn];
int num;
char s[maxn];
int cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for (i=0; i<m; i++) w[i]=0;
for (i=0; i<n; i++) w[x[i]=r[i]]++;
for (i=1; i<m; i++) w[i]+=w[i-1];
for (i=n-1; i>=0; i--) sa[--w[x[i]]]=i;
for (p=1,j=1; p<n; m=p,j*=2)
{
for (p=0,i=n-j; i<n; i++) y[p++]=i;
for (i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (i=0; i<m; i++) w[i]=0;
for (i=0; i<n; i++) w[wv[i]=x[y[i]]]++;
for (i=1; i<m; i++) w[i]+=w[i-1];
for (i=n-1; i>=0; i--) sa[--w[wv[i]]]=y[i];
for (t=x,x=y,y=t,x[sa[0]]=0,p=1,i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
return;
}
void cal(int *r,int *sa,int n)
{
int i,j,k=0;
for (i=1; i<=n; i++) rank[sa[i]]=i;
for (i=0; i<n; height[rank[i++]]=k)
for (k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
return;
}
int nmin(int a,int b)
{
return a<b?a:b;
}
void rmq(int n)
{
int i,j;
for (i=1; i<=n; i++)
f[i][0]=height[i];
for (j=1; j<20; j++)
for (i=1; i+(1<<j)-1<=n; i++)
f[i][j]=nmin(f[i][j-1],f[i+(1<<j-1)][j-1]);
return;
}
int lcp(int a,int b)
{
int x=rank[a],y=rank[b];
if (x>y)
{
int t=x;
x=y;
y=t;
}
x++;
int t=ft[y-x+1];
return nmin(f[x][t],f[y-(1<<t)+1][t]);
}
int main()
{
int cas=1;
int i;
char x;
for (i=0; i<maxn; i++) ft[i]=int(double(log(i*1.00))/log(2.00));
while (scanf("%s",s)!=EOF)
{
if(s[0]=='#') break;
n=strlen(s);
for (i=0; i<n; i++) a[i]=(int)s[i];
a[n]=0;
da(a,sa,n+1,128);
cal(a,sa,n);
rmq(n);
int k,max=0,r=0,t;
num=0;
for(int l=1; l<n; l++)//枚举长度
for(int i=0; i+l<n; i+=l)
{
k=lcp(i,i+l);
r=k/l+1;//注意为什么是k/l+1
t=i-(l-k%l);
if (t>=0&&k%l!=0)
if (lcp(t,t+l)>=k) r++;
if (r>max)
{
num=0;
len[++num]=l;
max=r;
}
else
if(r==max)
{
len[++num]=l;
}
//printf("l=%d r=%d i=%d i+l=%d/n",l,r,i,i+l);
}
// printf("%d/n",max);
int start,l;
for(int i=1;i<n;++i)//sa应从1开始,因为sa[0]是0
{
int ts=sa[i];//枚举这个开始
for(int j=1;j<=num;++j)
{
int tl=len[j];
if(lcp(ts,ts+tl)>=(max-1)*tl)
{
start=ts;
l=tl*max;
i=n;
break;
}
}
}
printf("Case %d: ", cas++);
for (int i = 0; i < l; i++) printf("%c", s[start+ i]);
cout<<endl;
}
return 0;
}
分享到:
相关推荐
2012百度之星资格赛试题与AC代码合集
百度之星答案
百度之星2012资格赛试题及答案讲解 题目全 等我总结好就传上答案讲解。方便码弄学习。交流下
在每组试验中,鑫哥选取了三个已经被准确标注在百度地图的坐标系里的移动运营商的基站作为信号接收点(这里可以准确的得到信号的接收时间信息)。当信号接收点附近的用户手机签到时,三个信号接收点就会先后接收到这...
接下去的K行中,每行包括两个时间,分别表示成“HH:MM”的格式,以空格分隔,分别对应了该蝌蚪团成员一个方便的时间段的开始时间、结束时间;例如09:00 10:00表明他在早上九点到十点的时间段是方便的,可以在百度...
Astar2007百度之星程序设计大赛网络资格赛(初赛) 题。 Astar2007百度之星程序设计大赛网络资格赛(初赛) 题 。
百度之星资格赛代码,我OJ了7道吧大约。
2010百度之星编程比赛坦克大战对战平台,说明文档
百度之星趣味赛——AK咆哮体 娱乐而已.....
2006 届百度之星编赛详解.很好很强大的东西。 值得我们去学习
百度电影推荐比赛参赛:评分预测问题.zip
界面略作修改,百度之星,百度棋,by--zjc,欢迎大家意见和建议。
百度之星试题,我也忘记是哪年的了。
百度之星历年赛题汇总- 很全面。对于参加比赛应该是比较好的资料,偶得,俺用不到,故分享赚分
这是百度之星比赛题目的程序设计题目和答案,,很有挑战必。。。。。。。。。。
从百度知道页面的“变形金刚”,手机版百度首页情人节特效,到百度首页的“2012世界末日,拯救地球”特效,再到今天百度首页的“端午赛龙舟”特效,百度的工程师们似乎正在给人们带来越来多的惊喜,而这些令人惊喜的...
希望之星英语比赛小学A组看图说话参考模拟题型PPT教案.pptx
有道2010_资格赛3 有道2010_资格赛3 有道2010_资格赛3
有道2010_资格赛1 有道2010_资格赛1 有道2010_资格赛1