4032: [HEOI2015]最短不公共子串
题目:传送门
题解:
陈年老题良心%你赛膜爆嘎爷
当初做题...一眼SAM...结果只会两种直接DP的情况...
情况1: 直接设f[i][j] 表示的是a串的第i个位置和b串的第j个位置开始的最长公共前缀(灵感来源于SA)。然后就枚举开头直接瞎搞啊。。。
情况2: 定义一个last[i][j] 表示b串的位置i后面的第一个字符j,贪心的思想直接做,匹配不到位置就直接记录答案了嘛
情况3: 因为是在b串当中找子串,a中找子序列,那就考虑对b建SAM,然后定义da[] 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度(具体看代码)、
情况4: 利用情况2预处理的last,贪心思想,仿照情况三把last当作自动机来跑
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define inf 1e9 7 using namespace std; 8 struct SAM 9 { 10 int son[50]; 11 }ch[5100];int cnt,dep[5100],a[5100],fail[5100],da[5100],la,root,ss;、 12 //da 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度 13 void add(int k) 14 { 15 int x=a[k]; 16 int p=la,np=++cnt;dep[np]=k; 17 while(p!=0 && ch[p].son[x]==0)ch[p].son[x]=np,p=fail[p]; 18 if(p==0)fail[np]=root; 19 else 20 { 21 int q=ch[p].son[x]; 22 if(dep[p]+1==dep[q])fail[np]=q; 23 else 24 { 25 int nq=++cnt;dep[nq]=dep[p]+1; 26 ch[nq]=ch[q];fail[nq]=fail[q];fail[np]=fail[q]=nq; 27 while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=fail[p]; 28 } 29 } 30 la=np; 31 } 32 int len1,len2,opt; 33 int c[50],last[2100][50];//位置i后面的第一个字符j 34 char sa[2100],sb[2100]; 35 int f[2100][2100];//分别以i,j位置开头的最长公共前缀 36 int main() 37 { 38 //freopen("a.in","r",stdin); 39 //freopen("a.out","w",stdout); 40 //scanf("%d",&opt); 41 scanf("%s",sa+1);len1=strlen(sa+1); 42 scanf("%s",sb+1);len2=strlen(sb+1); 43 //if(opt==1) 44 //{ 45 memset(f,0,sizeof(f));int ans=inf,len=0,maxx=0; 46 for(int i=len1;i>=1;i--)for(int j=len2;j>=1;j--)if(sa[i]==sb[j])f[i][j]=f[i+1][j+1]+1; 47 for(int i=1;i<=len1;i++) 48 { 49 maxx=0;for(int j=1;j<=len2;j++)maxx=max(maxx,f[i][j]); 50 if(maxx!=len1-i+1)ans=min(ans,maxx+1);//加一定不相等 51 } 52 if(ans==inf)printf("-1 "); 53 else printf("%d ",ans); 54 //} 55 //else if(opt==2) 56 //{ 57 len=0,ans=inf;for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a'; 58 for(int i=len2;i>=0;i--){for(int j=1;j<=26;j++)last[i][j]=c[j];c[sb[i]-'a'+1]=i;} 59 for(int i=1;i<=len1;i++) 60 { 61 len=0; 62 for(int j=i;j<=len1;j++) 63 { 64 len=last[len][sa[j]-'a'+1]; 65 if(len>len1){ans=min(ans,j-i+1);break;}//跳出去证明没有了 66 } 67 } 68 if(ans==inf)printf("-1 "); 69 else printf("%d ",ans); 70 //} 71 // else if(opt==3) 72 // { 73 cnt=0;root=la=++cnt;memset(da,63,sizeof(da)); 74 for(int i=1;i<=len2;i++)a[i]=sb[i]-'a';for(int i=1;i<=len2;i++)add(i);ss=0;da[1]=0;ans=inf; 75 for(int i=1;i<=len1;i++) 76 for(int j=1;j<=cnt;j++) 77 { 78 ss=ch[j].son[sa[i]-'a']; 79 if(ss==0)ans=min(ans,da[j]+1);else da[ss]=min(da[ss],da[j]+1); 80 } 81 if(ans==inf)printf("-1 "); 82 else printf("%d ",ans); 83 // } 84 //else if(opt==4) 85 //{ 86 ans=inf;//for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a'; 87 //for(int i=len2;i>=0;i--){for(int j=1;j<=26;j++)last[i][j]=c[j];c[sb[i]-'a'+1]=i;} 88 memset(da,63,sizeof(da));da[0]=0;ss=0; 89 for(int i=1;i<=len1;i++) 90 for(int j=len2;j>=0;j--) 91 { 92 ss=last[j][sa[i]-'a'+1]; 93 if(ss>len1)ans=min(ans,da[j]+1);else da[ss]=min(da[ss],da[j]+1); 94 } 95 if(ans==inf)printf("-1 "); 96 else printf("%d ",ans); 97 //} 98 return 0; 99 }