• [CF49E]Common ancestor


    [CF49E]Common ancestor

    题目大意:

    有两个由小写字母构成的字符串(S)(T(|S|,|T|le50))。另有(n(nle50))个形如(a o 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
    ",g[n][m]==INT_MAX?-1:g[n][m]);
    	return 0;
    }
    
  • 相关阅读:
    Redis数据持久化机制AOF原理分析一---转
    Linux中常用头文件的作用--转
    Signal Handling--ref
    Linux 信号signal处理函数--转
    深入redis内部--初始化服务器
    haproxy 503 service unavailable no server is avaible to handle this request
    linux下logrotate配置和理解---转
    extjs_09_定义自己的页面组件
    BZOJ 3211 弗洛拉前往国家 树阵+并检查集合
    atitit.无损传输二进制数据串传输网络
  • 原文地址:https://www.cnblogs.com/skylee03/p/10107844.html
Copyright © 2020-2023  润新知