bzoj 4032 [HEOI2015]最短不公共子串 后缀trie

来源:互联网 发布:淘宝网中老年服装品牌 编辑:程序博客网 时间:2024/05/17 06:21

对b建一个后缀trie
第一问枚举a的起点,在b的后缀trie上跑。
求出a,b每个位置加一个字符后会转移到的位置na,nb。
第二问枚举a的起点,b在nb上转移。
第三问dfs b的后缀trie,a在na上转移。
第四问dp f[i][j]表示a到i,b到j时a最短的长度。

#include <bits/stdc++.h>using namespace std;#define N 2100#define M 2100000int cnt,l1,l2,ans;char a[N],b[N];int na[N][26],nb[N][26],ch[M][26],pos[26];int f[N][N];void dfs(int x,int y,int deep){    if(y==l1+1)return;    if(!x){ans=min(ans,deep);return;}    for(int i=0;i<26;i++)        dfs(ch[x][i],na[y][i],deep+1);}int main(){    //freopen("tt.in","r",stdin);    scanf("%s%s",a+1,b+1);    l1=strlen(a+1);l2=strlen(b+1);    cnt=1;    for(int i=1;i<=l2;i++)        for(int j=i,now=1;j<=l2;j++)        {            if(!ch[now][b[j]-'a'])                ch[now][b[j]-'a']=++cnt;            now=ch[now][b[j]-'a'];        }    ans=l1+1;    for(int i=1;i<=l1;i++)        for(int j=i,now=1;j<=l1;j++)        {            if(!ch[now][a[j]-'a'])                {ans=min(ans,j-i+1);break;}            now=ch[now][a[j]-'a'];        }    printf("%d\n",ans==l1+1 ? -1:ans);    for(int i=0;i<26;i++)pos[i]=l2+1;    for(int i=l2;i>=0;i--)    {        memcpy(nb[i],pos,sizeof(pos));        pos[b[i]-'a']=i;    }    for(int i=0;i<26;i++)pos[i]=l1+1;    for(int i=l1;i>=0;i--)    {        memcpy(na[i],pos,sizeof(pos));        pos[a[i]-'a']=i;    }    ans=l1+1;    for(int i=1;i<=l1;i++)        for(int j=i,now=0;j<=l1;j++)        {            if(nb[now][a[j]-'a']==l2+1)                {ans=min(ans,j-i+1);break;}            now=nb[now][a[j]-'a'];        }    printf("%d\n",ans==l1+1 ? -1:ans);    ans=l1+1;dfs(1,0,0);    printf("%d\n",ans==l1+1 ? -1:ans);    ans=l1+1;    memset(f,0x3f,sizeof(f));    f[0][0]=0;    for(int i=0;i<=l1;i++)        for(int j=0;j<=l2;j++)            for(int k=0;k<26;k++)                f[na[i][k]][nb[j][k]]=min(f[i][j]+1,f[na[i][k]][nb[j][k]]);    for(int i=1;i<=l1;i++)        ans=min(ans,f[i][l2+1]);    printf("%d\n",ans==l1+1 ? -1:ans);    return 0;}
0 0
原创粉丝点击