【贪心】【后缀自动机】Gym - 101466E - Text Editor
2018-01-26 08:41
507 查看
题意:给你两个串A,B,以及一个整数K,让你找到B的一个尽可能长的前缀,使得其在A串中出现的次数不小于K次。
对A串建立后缀自动机,然后把B串放在上面跑,由于每到一个结点,该结点endpos集合的大小就是该前缀出现的次数,又由于较长前缀的出现次数不大于较短前缀,所以只要跑到不满足条件停下即可。
对A串建立后缀自动机,然后把B串放在上面跑,由于每到一个结点,该结点endpos集合的大小就是该前缀出现的次数,又由于较长前缀的出现次数不大于较短前缀,所以只要跑到不满足条件停下即可。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXL 100000 #define MAXC 300 int v[2*MAXL+10],__next[2*MAXL+10],first[2*MAXL+10],e; void AddEdge(int U,int V){ v[++e]=V; __next[e]=first[U]; first[U]=e; } char s[MAXL+10]; int len; struct SAM{ int endcnt[2*MAXL+10]; int n,maxlen[2*MAXL+10],minlen[2*MAXL+10],trans[2*MAXL+10][MAXC],slink[2*MAXL+10]; void clear(){ for(int i=0;i<=n;++i){ endcnt[i]=maxlen[i]=minlen[i]=slink[i]=first[i]=0; memset(trans[i],0,sizeof(trans[i])); } n=e=0; } int new_state(int _maxlen,int _minlen,int _trans[],int _slink){ maxlen =_maxlen; minlen =_minlen; for(int i=0;i<MAXC;++i){ if(_trans==NULL){ trans [i]=-1; } else{ trans [i]=_trans[i]; } } slink =_slink; return n++; } int add_char(char ch,int u){ if(u==-1){ return new_state(0,0,NULL,-1); } int c=ch; int z=new_state(maxlen[u]+1,-1,NULL,-1); endcnt[z]=1; int v=u; while(v!=-1 && trans[v][c]==-1){ trans[v][c]=z; v=slink[v]; } if(v==-1){ minlen[z]=1; slink[z]=0; return z; } int x=trans[v][c]; if(maxlen[v]+1==maxlen[x]){ minlen[z]=maxlen[x]+1; slink[z]=x; return z; } int y=new_state(maxlen[v]+1,-1,trans[x],slink[x]); slink[y]=slink[x]; minlen[x]=maxlen[y]+1; slink[x]=y; minlen[z]=maxlen[y]+1; slink[z]=y; int w=v; while(w!=-1 && trans[w][c]==x){ trans[w][c]=y; w=slink[w]; } minlen[y]=maxlen[slink[y]]+1; return z; } void dfs(int U){ for(int i=first[U];i;i=__next[i]){ dfs(v[i]); endcnt[U]+=endcnt[v[i]]; } } void work_slink_tree(){ for(int i=1;i<n;++i){ AddEdge(slink[i],i); } dfs(0); } }sam; typedef long long ll; char s2[MAXL+10]; int len2,K; int main(){ gets(s); len=strlen(s); int U=sam.add_char(0,-1); for(int i=0;i<len;++i){ U=sam.add_char(s[i],U); } sam.work_slink_tree(); gets(s2); len2=strlen(s2); scanf("%d",&K); int ans=0; U=0; for(int i=0;i<len2;++i){ if(sam.endcnt[U]<K){ ans=i-1; goto OUT; } else if(sam.trans[U][s2[i]]==-1){ ans=i; goto OUT; } U=sam.trans[U][s2[i]]; } ans=len2; if(sam.endcnt[U]<K){ ans=len2-1; goto OUT; } OUT: if(ans==0){ puts("IMPOSSIBLE"); } else{ for(int i=0;i<ans;++i){ putchar(s2[i]); } puts(""); } return 0; }
相关文章推荐
- XIII Open Championship of Y.Kupala Grodno SU Grodno Problem E. Enter the Word Problem 贪心+后缀自动机
- BZOJ_2099_[Usaco2010 Dec]Letter 恐吓信_后缀自动机+贪心
- 【hiho挑战赛24 A&B&C】贪心和期望dp惨烈的后缀自动机
- [hihoCoder挑战赛24](贪心)(期望DP)(后缀自动机)
- [BZOJ3998][TJOI2015]弦论(后缀自动机+拓扑排序+贪心)
- 【贪心】【后缀自动机】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem E. Enter the Word
- hdu 6208 The Dominator of Strings 后缀自动机 LCS
- codeforces 579D D. "Or" Game(前后缀+贪心)
- BZOJ 4516 后缀自动机
- [BZOJ3998] [TJOI2015] 弦论 - 后缀自动机
- codevs 3160(后缀自动机复习)
- Gym 101201I Postman (贪心)
- spoj 7258 Lexicographical Substring Search (后缀自动机)
- 后缀自动机 重复旋律 5(求所有本质不同的子串)
- BZOJ 4566: [Haoi2016]找相同字符 后缀自动机
- hdu4622 后缀自动机 模板
- 【贪心】Gym - 101201I - Postman
- 【字符串】后缀自动机小结
- 【bzoj3998】[TJOI2015]弦论 后缀自动机+dp
- SPOJ 1812 Longest Common Substring II(后缀自动机)