码迷,mamicode.com
首页 > 其他好文 > 详细

[CF49E]Common ancestor

时间:2018-12-12 13:51:11      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:信息   dig   --   最小   mit   oid   class   lin   字符串   

[CF49E]Common ancestor

题目大意:

有两个由小写字母构成的字符串\(S\)\(T(|S|,|T|\le50)\)。另有\(n(n\le50)\)个形如\(a\to bc\)的信息,表示可以将字符\(a\)替换为\(bc\)。定义两个字符串\(s,T\)的祖先\(R\)为能够通过若干次替换,使得其既可以变为\(S\),又可以变为\(T\)的字符串。求\(|R|\)的最小值。

思路:

首先分别预处理\(S,T\)中每一段是否可以通过单个字符转化过来,如果能,可以从哪些字符开始转化。然后枚举\(S,T\)匹配的位置和最后一次匹配到的段,如果最后匹配到的段都可以表示成一个相同的字母,那么就可以转移。

时间复杂度\(\mathcal O(l^4+26^2l^3)\)

源代码:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<climits>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
inline char getalpha() {
    register char ch;
    while(!isalpha(ch=getchar()));
    return ch;
}
const int N=52,S=26;
char s[N],t[N];
int map[S][S],f[2][N][N],g[N][N];
inline int idx(const char &ch) {
    return ch-'a';
}
inline void solve(const char s[],const int &n,int f[N][N]) {
    for(register int i=1;i<=n;i++) {
        f[i][i]|=1<<idx(s[i]);
    }
    for(register int i=1;i<=n;i++) {
        for(register int j=i-1;j;j--) {
            for(register int k=j;k<i;k++) {
                for(register int a=0;a<26;a++) {
                    if(!(f[j][k]>>a&1)) continue;
                    for(register int b=0;b<26;b++) {
                        if(!(f[k+1][i]>>b&1)) continue;
                        f[j][i]|=map[a][b];
                    }
                }
            }
        }
    }
}
int main() {
    scanf("%s%s",&s[1],&t[1]);
    for(register int i=getint();i;i--) {
        const char a=getalpha(),b=getalpha(),c=getalpha();
        map[idx(b)][idx(c)]|=1<<idx(a);
    }
    const int n=strlen(&s[1]),m=strlen(&t[1]);
    solve(s,n,f[0]);
    solve(t,m,f[1]);
    for(register int i=0;i<=n;i++) {
        for(register int j=0;j<=m;j++) {
            g[i][j]=INT_MAX;
        }
    }
    g[0][0]=0;
    for(register int i=1;i<=n;i++) {
        for(register int j=1;j<=m;j++) {
            for(register int k=1;k<=i;k++) {
                for(register int l=1;l<=j;l++) {
                    if(!(f[0][k][i]&f[1][l][j])) continue;
                    if(g[k-1][l-1]==INT_MAX) continue;
                    g[i][j]=std::min(g[i][j],g[k-1][l-1]+1);
                }
            }
        }
    }
    printf("%d\n",g[n][m]==INT_MAX?-1:g[n][m]);
    return 0;
}

[CF49E]Common ancestor

标签:信息   dig   --   最小   mit   oid   class   lin   字符串   

原文地址:https://www.cnblogs.com/skylee03/p/10107844.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!