【编程网格无水题】之【最短歧义串】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/csdnicewing/article/details/78878263

一个小小的字符串,一个三岁小孩都能把它删掉,但它却可以累死所有的程序员……

就好比这道题,累死我了。

首先声明,算法来自于百度贴吧的 patricia_xiao 前辈,非常感谢,本蒟蒻不生产算法,我只是算法的搬运工。

附原帖地址http://tieba.baidu.com/p/2048370484

闲话结束,下面上题

考虑一个歧义串会有什么样的结构

拿样例为例,iskill ,它可以拆分成 I 和 skill,也可以拆成 is 和 kill

那么不同的拆分方式是什么意思呢?

就是is 可以严格包含I ,剩下字串s 可以被 skill 严格包含 ,而skill 剩下的字串  kill 呢又等于字典中原有的  kill

这样就构造好了一个歧义串。所以不同拆分的意思就是完美包含 

有同学说自己case8总是空输出,怎么回事呢?

比如说A被B完美包含,B截掉A剩下的字串啊,很可能巨长……没有字典中的原串可以包含它,但它却可以包含字典中的某些原串……

那就看它能包含字典中哪些原串喽,再截短

显而易见,退出条件就是这个剩下的字串和字典中某个原串相等(或者再走一步,剩下的字串为0,但不推荐这么想,因为有违歧义的原则)。

敲黑板!!!这题感觉单词不能重复用,所以一定要标记哪些串用过了,不标记100%TLE (跟我念,te le,这单词不念T L E)

下面上代码(注释是方便调试的时候搞事情的,因为我很懒,懒得装编程环境所以一直在用在线IDE)

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<climits>
#include<cmath>
using namespace std;
string dic[110];
bool used[110];
int n,ans;
string astr;


void dfs(string substr,int templ,string tans){
    //cout<<substr<<"mark"<<endl;
    //cout<<tans<<endl;
        for(int i=0;i<n;i++){
        if(!used[i]){
            //cout<<dic[i]<<endl;
            if(dic[i]==substr){
                if(ans>templ+substr.length()){
                     ans=templ+substr.length();
                     astr=tans+substr;
                }
                return;
            }else if(dic[i].length()>substr.length()&&dic[i].find(substr,0)==0){
                used[i]=true;
                string tstr=dic[i].substr(substr.length(),dic[i].length()-substr.length());
                dfs(tstr,templ+substr.length(),tans+substr);
                used[i]=false;
            }else if(dic[i].length()<substr.length()&&substr.find(dic[i],0)==0){
                used[i]=true;
                string tstr=substr.substr(dic[i].length(),substr.length()-dic[i].length());
                dfs(tstr,templ+dic[i].length(),tans+dic[i]);
                used[i]=false;
            }
        }
    }    
    return;
}


int main(){
    ans=INT_MAX;
    memset(used,0,sizeof(used));
    scanf("%d\n",&n);
    for(int i=0;i<n;i++)
        cin>>dic[i];
    sort(dic,dic+n);
    for(int i=1;i<n;i++){
        for(int j=0;j<i;j++){
            if(dic[i].find(dic[j],0)==0&&dic[i]!=dic[j]){
                used[i]=true;
                used[j]=true;
                const string tstr=dic[i].substr(dic[j].length(),dic[i].length()-dic[j].length());
                dfs(tstr,dic[j].length(),dic[j]);
                used[i]=false;
                used[j]=false;
            }
        }
    }
   // printf("%d\n",ans);
    cout<<astr;
    return 0;
}
最后,黄旭东祝大家考啥啥挂(手动滑稽)听说昨晚黄旭东和局座一起做客B站,咳咳咳,简直生化危机,非抗奶人员请迅速撤离……

猜你喜欢

转载自blog.csdn.net/csdnicewing/article/details/78878263
今日推荐