bzoj 1398 寻找主人 Necklace
Description
给定两个项链的表示,判断他们是否可能是一条项链。
Input
输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。
Output
如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’
第二行输出该项链的字典序最小的表示。 设L = 项链长度,L <= 1000000。
Sample Input
2234342423
2423223434
2423223434
Sample Output
Yes
2234342423
2234342423
这题用最小表示法$O(n)$的做法,或者用后缀数组和后缀自动机都可以做。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=1000000+100; 4 char s1[N],s2[N]; 5 int solve(char *s){ 6 int len=strlen(s); 7 int i=0,j=1,k=0; 8 while (i<len && j<len && k<len){ 9 int t=s[(i+k)%len]-s[(j+k)%len]; 10 if(!t) k++; 11 else { 12 if(t>0) i+=k+1; 13 else if(t<0) j+=k+1; 14 if(i==j) j++; 15 k=0; 16 } 17 } 18 return min(i,j); 19 } 20 21 int main(){ 22 scanf("%s",s1); 23 int t1=solve(s1); 24 scanf("%s",s2); 25 int t2=solve(s2); 26 int check=0; 27 int len1=strlen(s1); 28 int len2=strlen(s2); 29 if(len1!=len2){ 30 puts("NO"); 31 return 0; 32 } 33 for(int i=0;i<len1;i++) 34 if( s1[(t1+i) % len1]!=s2[(t2+i)%len1] ) 35 check=1; 36 if(check){ 37 puts("No"); 38 return 0; 39 } 40 puts("Yes"); 41 for(int i=0;i<len1;i++) 42 putchar(s1[(t1+i)%len1]); 43 return 0; 44 }
后缀自动机写法,由于要超空间,所以使用了链表的方法来存储边。 虽然也可以过,但是比之前的方法慢了很多。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=1900000+10; 4 int fa[N<<1],len[N<<1]; 5 struct Edge{ 6 int to,nt,w; 7 }e[N<<1]; 8 char s[1000001]; 9 int ls,tot,cnt,h[N<<1],id,lk[N<<1]; 10 void inline addedge(int a,int b,int c){ 11 e[++cnt].to=b; 12 e[cnt].w=c; 13 e[cnt].nt=h[a]; 14 h[a]=cnt; 15 } 16 int inline son(int x,int y){ 17 for(int i=h[x];i;i=e[i].nt) 18 if(e[i].w==y) { 19 id=i; 20 return e[i].to; 21 } 22 return 0; 23 } 24 void add(int c){ 25 int p=ls; 26 int np=ls=++tot; 27 len[np]=len[p]+1; 28 for(;p &&!son(p,c);p=fa[p]) addedge(p,np,c); 29 if(!p) fa[np]=1; 30 else { 31 int q=son(p,c); 32 if(len[q]==len[p]+1) fa[np]=q; 33 else { 34 int nq=++tot; 35 fa[nq]=fa[q]; 36 for(int i=h[q];i;i=e[i].nt) 37 addedge(nq,e[i].to,e[i].w); 38 len[nq]=len[p]+1; 39 fa[q]=fa[np]=nq; 40 for(;p && son(p,c)==q;p=fa[p]) 41 e[id].to=nq; 42 } 43 } 44 } 45 void solve(char *s){ 46 int p=1; 47 for(int i=0;s[i];i++){ 48 int c=s[i]-48; 49 if(!son(p,c)) { 50 puts("No"); 51 exit(0); 52 } 53 p=son(p,c); 54 } 55 } 56 int main(){ 57 scanf("%s",s); 58 int len1=strlen(s); 59 tot=ls=1; 60 for(int i=0;s[i];i++) 61 add(s[i]-48); 62 for(int i=0;s[i];i++) 63 add(s[i]-48); 64 scanf("%s",s); 65 int len2=strlen(s); 66 if(len1!=len2){ 67 puts("No"); 68 return 0; 69 } 70 solve(s); 71 vector<int> num(len1+2<<1); 72 vector<int> sa(len1+2<<2); 73 for(int i=1;i<=tot;i++) num[len[i]]++; 74 for(int i=1;i<=2*len1;i++) num[i]+=num[i-1]; 75 for(int i=1;i<=tot;i++) sa[num[len[i]]--]=i; 76 num.clear(); 77 sa.clear(); 78 for(int i=tot;i>=1;i--){ 79 int t=sa[i]; 80 int f=fa[t]; 81 for(int j=h[t];j;j=e[j].nt){ 82 int v=e[j].to; 83 if(!v) continue; 84 lk[t]=max(lk[t],lk[v]+1); 85 } 86 } 87 puts("Yes"); 88 int p=1; 89 for(int i=0;i<len1;i++){ 90 for(int j=0;j<10;j++){ 91 int t=son(p,j); 92 if(!t) continue; 93 if(lk[t]+i+1<len1) continue; 94 putchar(48+j); 95 p=t; 96 break; 97 } 98 } 99 return 0 ; 100 }