zoukankan      html  css  js  c++  java
  • 题解 【POJ1934】 Trip

    题目意思:

    有两个字符串(长度(<=80)),按字典序输出它们的最长公共子串的所有情况.

    解析

    最长公共子序列的长度应该都没问题了吧...有问题请自行百度

    但关键是要求出每种情况,还要按字典序...

    考虑到长度(<=80),我们可以用搜索+剪枝,

    设两个串为(a),(b),长度为(la),(lb),

    (f[i][j])表示(a)串中的(1)~(i)(b)串中的$ 1(~)j$的最长公共子序列的长度.

    先求出最长公共子序列的长度(len)=(f[la][lb]),

    那么.我们就是要求出一个长度为(len)(a),(b),的子串,

    我们再设(f1[i][j])表示在(a)串的(1)~(j)中,字母(i)出现的最后一个位置,

    (f2[i][j])就表示(b)串,其中(i)(1)~(26),

    那么在搜索时,记录(4)个信息:(a)串还能取的长度(l1),(b)串还能取的长度(l2),当前求出的子串(s)和还需要求的子串的长度(l).

    那么,在一开始时,状态就应该是((la,lb,"",len)),其中(s)是一个空串.

    那么,在搜索时枚举每个字母(ci),设(p1)表示(f1[ci][l1]),(p2)表示(f2[ci][l2]),

    那么,若(f[p1][p2]>=l),即最终能形成长度为(len)的子串,就将(ci)加入(s),

    并且注意,由于我们是倒着搜的,所以要用(ci+s)而不是(s+ci).

    (l1)(l2)小于(0)时,即搜不到了,就返回,

    而当(l)等于(0)时就添加答案并返回.

    最后排序后输出就行了.

    具体实现看代码吧:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return f*sum;
    }
    
    int f[101][101],tot=0;
    char a[101],b[101];
    int f1[27][101],f2[27][101];
    string ans[1001];
    
    void find(int l1,int l2,string s,int l){
    	if(l1<0||l2<0) return ;
    	if(l<=0){ans[++tot]=s;return ;}
    	for(int i=1;i<=26;i++){
    		int p1=f1[i][l1],p2=f2[i][l2];
    		if(f[p1][p2]!=l) continue;
    		char c=i+96;
    		find(p1-1,p2-1,c+s,l-1);
    	}
    }
    
    int main(){
    	cin>>a>>b;
    	int la=strlen(a),lb=strlen(b);
    	for(int i=la;i;i--) a[i]=a[i-1];
    	for(int i=lb;i;i--) b[i]=b[i-1];//这两步是整体位移,个人习惯而已
    	for(int i=1;i<=26;i++){
    		for(int j=1;j<=la;j++){
    			if(a[j]==i+96) f1[i][j]=j;
    			else f1[i][j]=f1[i][j-1];
    		}
    		for(int j=1;j<=lb;j++){
    			if(b[j]==i+96) f2[i][j]=j;
    			else f2[i][j]=f2[i][j-1];
    		}
    	}//记录f1,f2
    	for(int i=1;i<=la;i++){
    		for(int j=1;j<=lb;j++){
    			f[i][j]=max(f[i-1][j],f[i][j-1]);
    			if(a[i]==b[j]) f[i][j]=max(f[i-1][j-1]+1,f[i][j]);
    		}
    	}//寻找最长公共子序列
    	find(la,lb,"",f[la][lb]);
    	sort(ans+1,ans+tot+1);
    	for(int i=1;i<=tot;i++) cout<<ans[i]<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    ES5和ES6中的静态方法、类、单例模式
    Koa 应用生成器以及 Koa 路由模块化
    封装 Koa操作Mongodb数据库的DB类库
    Koa Session 的使用
    Koa 中 Cookie 的使用
    koa art-template 模板引擎
    koa koa-static 静态资源中间件
    koa post 提交数据 koa-bodyparser 中间件的使用
    koa ejs 模板引擎
    详解express与koa中间件执行顺序模式分析
  • 原文地址:https://www.cnblogs.com/zsq259/p/10644253.html
Copyright © 2011-2022 走看看