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; }