bzoj 1398 寻找主人 Necklace

Description

给定两个项链的表示,判断他们是否可能是一条项链。

Input

输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。

Output

如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’
第二行输出该项链的字典序最小的表示。 设L = 项链长度,L <= 1000000。

Sample Input

2234342423
2423223434

Sample Output

Yes
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 } 
View Code

 后缀自动机写法,由于要超空间,所以使用了链表的方法来存储边。 虽然也可以过,但是比之前的方法慢了很多。  

  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 }    
View Code

 

 

 
posted @ 2019-06-18 14:02  zjxxcn  阅读(166)  评论(0编辑  收藏  举报