【2012百度之星/资格赛】H:用户请求中的品牌
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                【2012百度之星/资格赛】H:用户请求中的品牌
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            時間限制:?1000ms? 內存限制:?65536kB 
 
 描述  輸入輸入數據包括多組,每組為一個全部由小寫字母組成的不含空格的用戶請求(字符串),占一行。用戶請求的長度不大于100,000。
最后一行輸入為#,作為結束的標志。 輸出對于每組輸入,先輸出這個組的編號(第n組就是輸出“Case n:”);然后輸出這組用戶請求中循環節最多的子串。如果一個用戶請求中有兩個循環節數相同的子串,請選擇那個字典序最小的。 樣例輸入 ilovejohnsonjohnsonverymuch
duckduckgo
aaabbbcccisagoodcompany
#  樣例輸出 Case 1: johnsonjohnson
Case 2: duckduck
Case 3: aaa  
 
 
大致思路:
??? 先窮舉長度L,然后求長度為L 的子串最多能連續出現幾次。首先連續出現1 次是肯定可以的,所以這里只考慮至少2 次的情況。假設在原字符串中連續出現2 次,記這個子字符串為S,那么S 肯定包括了字符r[0]、 r[L]、 r[L*2]、r[L*3] ……中的某相鄰的兩個。所以只須看字符r[L*i]和r[L*(i+1)]往前和往后各能匹配到多遠,記這個總長度為K,那么這里連續出現了K/L+1 次。最后看最大值是多少。
實現代碼:
#include<iostream> #include<cstdio> using namespace std; #include<string.h> #include<math.h>int wa[200000],wb[200000],wv[200000],wsum[200000]; int height[200000],sa[200000],rank[200000]; int n,ans,len,pos; char str[200000]; int R[200000]; int f[200000][20]; int a[200000],num; 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)?? //倍增算法 r為待匹配數組? n為總長度 m為字符范圍 {int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;++i)wsum[i]=0;for(i=0;i<n;++i)wsum[x[i]=r[i]]++;for(i=1;i<m;++i)wsum[i]+=wsum[i-1];for(i=n-1;i>=0;--i)sa[--wsum[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){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<n;i++)wv[i]=x[y[i]];for(i=0;i<m;++i)wsum[i]=0;for(i=0;i<n;++i)wsum[wv[i]]++;for(i=1;i<m;i++)wsum[i]+=wsum[i-1];for(i=n-1;i>=0;--i)sa[--wsum[wv[i]]]=y[i];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;} } void calheight(int *r,int *sa,int n)???? //求height數組 {int i,j,k=0;for(i=0;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++); } int mmin(int x,int y) {return x<y?x:y; } void rmqinit(int n)???? //初始化rmq {int i,j,k,m;m=(int)(log(1.0*n)/log(2.0)); for(i=1;i<=n;i++) f[i][0]=height[i]; for(i=1;i<=m;++i) for(j=n;j>=1;--j) { f[j][i]=f[j][i-1]; k=1<<(i-1); if(j+k<=n) f[j][i]=mmin(f[j][i],f[j+k][i-1]); } } int get_rmq(int x , int y)??? //詢問x、y后綴的最長公共前綴 ? { int m,t; x=rank[x] , y=rank[y]; if(x>y)? ?t=x,x=y,y=t;? ?++x;? ?m=(int)(log(1.0*(y-x+1))/log(2.0));? ?return mmin(f[x][m],f[y-(1<<m)+1][m]);? ? } int main(void) {int i,j,k,ca=0,l,s,t,p,cnt;char c;while(scanf("%s",str)!=EOF){if(str[0]=='#')break;n=strlen(str);for(i=0;i<n;++i)R[i]=str[i]-'a'+1;R[n]=0;da(R,sa,n+1,28);calheight(R,sa,n);rmqinit(n);ans=1;num=0;pos=0;for(l=1;l<=n/2;++l)??????????? //枚舉長度{for(i=0;i<n-l;i+=l){if(str[i]!=str[i+l])continue;k=get_rmq(i,i+l);s=k/l+1;p=i;t=l-k%l;cnt=0;for(j=i-1;j>=0 && j>i-l && str[j]==str[j+l];j--){++cnt;if(cnt==t)s++ , p=j;else if(rank[j]<rank[p])p=j;}if(ans<s){pos=p;len=s*l;ans=s;}else if(ans==s && rank[pos]>rank[p]){pos=p;len=s*l;}}}printf("Case %d: ",++ca);if(ans<2){c='z';for(i=0;i<n;++i)if(str[i]<c)c=str[i];printf("%c\n",c);continue;}for(i=0;i<len;++i)printf("%c",str[i+pos]);puts("");}return 0; }
                            
                        
                        
                         餡餅同學是一個在百度工作,做用戶請求(query)分析的同學,他在用戶請求中經常會遇到一些很奇葩的詞匯。在比方說“johnsonjohnson”、“duckduck”,這些詞匯雖然看起來是一些詞匯的單純重復,但是往往都是一些特殊品牌的詞匯,不能被拆分開。為了偵測出這種詞的存在,你今天需要完成我給出的這個任務——“找出用戶請求中循環節最多的子串”。
 
最后一行輸入為#,作為結束的標志。
??? 先窮舉長度L,然后求長度為L 的子串最多能連續出現幾次。首先連續出現1 次是肯定可以的,所以這里只考慮至少2 次的情況。假設在原字符串中連續出現2 次,記這個子字符串為S,那么S 肯定包括了字符r[0]、 r[L]、 r[L*2]、r[L*3] ……中的某相鄰的兩個。所以只須看字符r[L*i]和r[L*(i+1)]往前和往后各能匹配到多遠,記這個總長度為K,那么這里連續出現了K/L+1 次。最后看最大值是多少。
實現代碼:
#include<iostream> #include<cstdio> using namespace std; #include<string.h> #include<math.h>int wa[200000],wb[200000],wv[200000],wsum[200000]; int height[200000],sa[200000],rank[200000]; int n,ans,len,pos; char str[200000]; int R[200000]; int f[200000][20]; int a[200000],num; 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)?? //倍增算法 r為待匹配數組? n為總長度 m為字符范圍 {int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;++i)wsum[i]=0;for(i=0;i<n;++i)wsum[x[i]=r[i]]++;for(i=1;i<m;++i)wsum[i]+=wsum[i-1];for(i=n-1;i>=0;--i)sa[--wsum[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){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<n;i++)wv[i]=x[y[i]];for(i=0;i<m;++i)wsum[i]=0;for(i=0;i<n;++i)wsum[wv[i]]++;for(i=1;i<m;i++)wsum[i]+=wsum[i-1];for(i=n-1;i>=0;--i)sa[--wsum[wv[i]]]=y[i];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;} } void calheight(int *r,int *sa,int n)???? //求height數組 {int i,j,k=0;for(i=0;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++); } int mmin(int x,int y) {return x<y?x:y; } void rmqinit(int n)???? //初始化rmq {int i,j,k,m;m=(int)(log(1.0*n)/log(2.0)); for(i=1;i<=n;i++) f[i][0]=height[i]; for(i=1;i<=m;++i) for(j=n;j>=1;--j) { f[j][i]=f[j][i-1]; k=1<<(i-1); if(j+k<=n) f[j][i]=mmin(f[j][i],f[j+k][i-1]); } } int get_rmq(int x , int y)??? //詢問x、y后綴的最長公共前綴 ? { int m,t; x=rank[x] , y=rank[y]; if(x>y)? ?t=x,x=y,y=t;? ?++x;? ?m=(int)(log(1.0*(y-x+1))/log(2.0));? ?return mmin(f[x][m],f[y-(1<<m)+1][m]);? ? } int main(void) {int i,j,k,ca=0,l,s,t,p,cnt;char c;while(scanf("%s",str)!=EOF){if(str[0]=='#')break;n=strlen(str);for(i=0;i<n;++i)R[i]=str[i]-'a'+1;R[n]=0;da(R,sa,n+1,28);calheight(R,sa,n);rmqinit(n);ans=1;num=0;pos=0;for(l=1;l<=n/2;++l)??????????? //枚舉長度{for(i=0;i<n-l;i+=l){if(str[i]!=str[i+l])continue;k=get_rmq(i,i+l);s=k/l+1;p=i;t=l-k%l;cnt=0;for(j=i-1;j>=0 && j>i-l && str[j]==str[j+l];j--){++cnt;if(cnt==t)s++ , p=j;else if(rank[j]<rank[p])p=j;}if(ans<s){pos=p;len=s*l;ans=s;}else if(ans==s && rank[pos]>rank[p]){pos=p;len=s*l;}}}printf("Case %d: ",++ca);if(ans<2){c='z';for(i=0;i<n;++i)if(str[i]<c)c=str[i];printf("%c\n",c);continue;}for(i=0;i<len;++i)printf("%c",str[i+pos]);puts("");}return 0; }
總結
以上是生活随笔為你收集整理的【2012百度之星/资格赛】H:用户请求中的品牌的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【2012百度之星/资格赛】F:百科蝌蚪
- 下一篇: 【2012百度之星 / 资格赛】I:地图
