1. 程式人生 > >bzoj 4032 [HEOI2015]最短不公共子串——字尾自動機

bzoj 4032 [HEOI2015]最短不公共子串——字尾自動機

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032

不是 b 的子串的話就對 b 建字尾自動機,在 a 上列舉從每個位置開始的子串或者找子序列(子序列就是記錄 a 的前 i 個,走到 b 的 j 狀態用的最短長度),對應到自動機上看看能不能走下去就行了。

不是 b 的子序列的話就對 b 建子序列自動機?就是那個知道每個位置再填一個字元會走到哪個位置的陣列。然後在 a 上列舉,看看自動機上能不能走下去就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using
namespace std; const int N=2005,M=4005,K=30; char a[N],b[N]; int n,m,cnt=1,lst=1,go[M][K],fa[M],l[M],nxt[N][K],lt[K]; int dp[N][M];//M//int int Mn(int a,int b){return a<b?a:b;} void add(int w) { int p=lst,np=++cnt;lst=np;l[np]=l[p]+1; for(;p&&!go[p][w];p=fa[p])go[p][w]=np; if(!p)fa[np]=1;
else { int q=go[p][w]; if(l[q]==l[p]+1)fa[np]=q; else { int nq=++cnt;l[nq]=l[p]+1; fa[nq]=fa[q];fa[q]=nq;fa[np]=nq; memcpy(go[nq],go[q],sizeof go[q]); for(;go[p][w]==q;p=fa[p])go[p][w]=nq; } } } void solve1() { int ans=n+1; for(int i=1;i<=n;i++) {
int cr=1; for(int j=i;j<=n;j++) { if(!go[cr][a[j]-'a'+1]) {ans=Mn(ans,j-i+1);break;} cr=go[cr][a[j]-'a'+1]; } } printf("%d\n",ans>n?-1:ans); } void solve2() { int ans=n+1; for(int t=1;t<=n;t++) { int cr=0; for(int i=t;i<=n;i++) { int d=a[i]-'a'+1; if(nxt[cr][d])cr=nxt[cr][d]; else {ans=Mn(ans,i-t+1);break;} } } printf("%d\n",ans>n?-1:ans); } void solve3() { memset(dp,0x3f,sizeof dp); dp[0][1]=0; int ans=n+1; for(int i=1;i<=n;i++) { int d=a[i]-'a'+1; for(int j=1;j<=cnt;j++) if(dp[i-1][j]<=n) { dp[i][j]=Mn(dp[i][j],dp[i-1][j]); if(!go[j][d])ans=Mn(ans,dp[i-1][j]+1); else dp[i][go[j][d]]=Mn(dp[i][go[j][d]],dp[i-1][j]+1); } } printf("%d\n",ans>n?-1:ans); } void solve4() { memset(dp,0x3f,sizeof dp); dp[0][0]=0; int ans=n+1; for(int i=1;i<=n;i++) { int d=a[i]-'a'+1; for(int j=0;j<=m;j++) if(dp[i-1][j]<=n) { dp[i][j]=Mn(dp[i][j],dp[i-1][j]); if(!nxt[j][d])ans=Mn(ans,dp[i-1][j]+1); else dp[i][nxt[j][d]]=Mn(dp[i][nxt[j][d]],dp[i-1][j]+1); } } printf("%d\n",ans>n?-1:ans); } int main() { scanf("%s",a+1);scanf("%s",b+1); n=strlen(a+1);m=strlen(b+1); for(int i=1;i<=m;i++)add(b[i]-'a'+1); for(int i=m;i>=0;i--) { for(int j=1;j<=26;j++) nxt[i][j]=lt[j]; lt[b[i]-'a'+1]=i; } solve1();solve2(); solve3();solve4(); return 0; }