1. 程式人生 > >【程式設計網格無水題】之【最短歧義串】

【程式設計網格無水題】之【最短歧義串】

一個小小的字串,一個三歲小孩都能把它刪掉,但它卻可以累死所有的程式設計師……

就好比這道題,累死我了。

首先宣告,演算法來自於百度貼吧的 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站,咳咳咳,簡直生化危機,非抗奶人員請迅速撤離……