CodeForces 427D Match & Catch
来源:互联网 发布:stc单片机是中国的吗 编辑:程序博客网 时间:2024/05/16 14:53
CodeForces 427D Match & Catch
SAM
题意
给两个串,求一个最小子串的长度,使得它是两个串的公共子串,且在两个子串中均只出现一次。
思路
对第一个串建自动机,求公共子串就是常规思路,不过跑的时候开个num数组记录,到一个点说明这个点代表的子串们出现了一次,记录这个次数,这是第二个串的次数。第一个串的次数在SAM中处理出来,那个endposamu数组。
至于每个状态,跑到了就说明这个状态的子串全部都出现过。所以最后取所有endposnum和num都为1的状态中minlen最小的值。
代码
别忘了无解输出-1
#include<bits/stdc++.h>#define M(a,b) memset(a,b,sizeof(a))typedef long long LL;using namespace std;const int MAXL=10005;const int MAXS=26;struct SAM{ int n=0, len, st; int maxlen[2*MAXL+10], minlen[2*MAXL+10], trans[2*MAXL+10][MAXS], slink[2*MAXL+10], col[2*MAXL+10], indeg[2*MAXL+10], endposamu[2*MAXL+10], num[2*MAXL+10]; int new_state(int _maxlen, int _minlen, int* _trans, int _slink) { n++; maxlen[n]=_maxlen; minlen[n]=_minlen; for(int i=0; i<MAXS; i++) { if(_trans==NULL) trans[n][i]=0; else trans[n][i]=_trans[i]; } slink[n]=_slink; return n; } int add_char(char ch, int u) { int c=ch-'a'; int z=new_state(maxlen[u]+1, -1, NULL, 0); col[z]=1; int v=u; while(v!=0&&trans[v][c]==0) { trans[v][c]=z; v=slink[v]; } if(v==0) { minlen[z]=1; slink[z]=1; indeg[1]++; return z; } int x=trans[v][c]; if(maxlen[v]+1==maxlen[x]) { minlen[z]=maxlen[x]+1; slink[z]=x; indeg[x]++; return z; } int y=new_state(maxlen[v]+1, -1, trans[x], slink[x]); col[y]=0; minlen[x]=maxlen[y]+1; slink[x]=y; minlen[z]=maxlen[y]+1; slink[z]=y; indeg[y]+=2; int w=v; while(w!=0&&trans[w][c]==x) { trans[w][c]=y; w=slink[w]; } minlen[y]=maxlen[slink[y]]+1; return z; } void init() { memset(col, 0, sizeof(col)); memset(indeg, 0, sizeof(indeg)); memset(maxlen, 0, sizeof(maxlen)); memset(minlen, 0, sizeof(maxlen)); memset(trans, 0, sizeof(maxlen)); memset(slink, 0, sizeof(maxlen)); memset(endposamu, 0, sizeof(endposamu)); memset(num, 0, sizeof(num)); n=0; st=new_state(0, -1, NULL, 0); } void getendpos() { queue<int> que; for(int i=st;i<=n;i++) { if(indeg[i]==0) que.push(i); if(col[i]==1) endposamu[i]++; } while(!que.empty()) { int pos=que.front();que.pop(); endposamu[slink[pos]]+=endposamu[pos]; indeg[slink[pos]]--; if(indeg[slink[pos]]==0) que.push(slink[pos]); } } void addstring(char* s,int len) { int la=st; for(int i=0;i<len;i++) { la=add_char(s[i], la); } getendpos(); } int match(char* s, int m) { int now=this->st; for(int i=0;i<m;i++) { int k=s[i]-'a'; if(trans[now][k]) { now=trans[now][k]; num[now]++; } else { while(!trans[now][k]&&now) { now=slink[now]; } if(!now) { now=this->st; } else { now=trans[now][k]; num[now]++; } } } int ans=0x3f3f3f3f; for(int i=this->st;i<=this->n;i++) { if(num[i]==1&&endposamu[i]==1) { ans=min(ans, minlen[i]); } } if(ans>=0x3f3f3f3f) return -1; return ans; }}sam;char ss[MAXL*2+7];int main(){ sam.init(); scanf("%s", ss); int n=strlen(ss); sam.addstring(ss, n); scanf("%s", ss); int m=strlen(ss); cout<<sam.match(ss, m)<<endl; //system("pause"); return 0;}
阅读全文
0 0
- Codeforces 427 D. Match & Catch
- CodeForces 427D-Match & Catch
- CodeForces 427D-Match & Catch
- CodeForces 427D Match & Catch
- codeforces 427 D Match & Catch ( 后缀数组 )
- Codeforces 427D Match & Catch 后缀自动机
- CodeForces 427D Match & Catch 后缀数组
- Codeforces 427D Match & Catch 后缀自动机 或 后缀数组
- Codeforces 427D Match & Catch(后缀自动机)
- CodeForces 427 D.Match & Catch(后缀数组)
- Codeforces Round #244 (Div. 2) D. Match & Catch
- Codeforces round 244(div.2) D match&catch【字符串hash】
- cf 427D Match & Catch 后缀数组
- CF(427D-Match & Catch)后缀数组应用
- CF 427D Match & Catch 求最短唯一连续LCS
- Codeforces Round #244 (Div. 2)——Match & Catch
- CF #244 (Div. 2) D Match & Catch (后缀数组 仅出现一次最短公共子串)
- Codeforces 427Div2 D、835D Palindromic characteristics
- 控制反转
- 初学Jsp
- Mybatis映射文件中的#{}与${}
- 928(1)
- python核心编程v2.0 第14章习题答案
- CodeForces 427D Match & Catch
- 使用translate对元素造成类似position:relative的影响
- ffmpeg(ubuntu16.04):视频抽成帧(图片)/图片合成视频
- matplotlib相关
- Android 系统服务的两种注册方式
- pygame字体
- tensorflow中nn的padding
- response.setContentType()与response.setCharacterEncoding()
- HASH+平衡树 [JSOI2008]火星人prefix