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

来源:互联网 发布:ai软件下载中文版 mac 编辑:程序博客网 时间:2024/04/28 07:41

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

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

首先声明,算法来自于百度贴吧的 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站,咳咳咳,简直生化危机,非抗奶人员请迅速撤离……