#include#include#includeusingnamespacestd;typedefpairword_index;typedefpairlv1_index;#defineNOT_VALUE0xfffffffftypedefstructdp_item{intmin_word_amount;intmin_word_seq[" />

黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

Timus 1002

系統(tǒng) 1955 0
      
        #include 
      
      
        <
      
      
        iostream
      
      
        >
      
      
        
#include
< string >
#include
< vector >
#include
< algorithm >
using namespace std;

typedef pair
< int , int > word_index;

typedef pair
< int , int > lv1_index;

#define NOT_VALUE 0xffffffff

typedef
struct dp_item {
int min_word_amount;
int min_word_seq[ 200 ]; // 最長(zhǎng)的word序列也就是100個(gè)單字母組成
} dp_item;


string words[ 100010 ];
dp_item dp[
200 ] = { 0 }; // 號(hào)碼最長(zhǎng)是100個(gè)字符
lv1_index index_lv1[ 100 ]; // 一級(jí)索引使用數(shù)組,不用vector,因?yàn)檫@樣可以更方便地根據(jù) 索引項(xiàng)的單詞長(zhǎng)度,隨機(jī)訪問一級(jí)索引,單個(gè)詞最長(zhǎng)也就50個(gè)字符

bool cmp_index( const word_index & a, const word_index & b) {

if ( a.second == b.second )
return a.first < b.first;

return a.second < b.second;
}

char letter_to_num( char letter) {
switch (letter) {
case ' i ' : case ' j ' : return ' 1 ' ;
case ' a ' : case ' b ' : case ' c ' : return ' 2 ' ;
case ' d ' : case ' e ' : case ' f ' : return ' 3 ' ;
case ' g ' : case ' h ' : return ' 4 ' ;
case ' k ' : case ' l ' : return ' 5 ' ;
case ' m ' : case ' n ' : return ' 6 ' ;
case ' p ' : case ' r ' : case ' s ' : return ' 7 ' ;
case ' t ' : case ' u ' : case ' v ' : return ' 8 ' ;
case ' w ' : case ' x ' : case ' y ' : return ' 9 ' ;
case ' o ' : case ' q ' : case ' z ' : return ' 0 ' ;
}
}

bool match( const string & sub_num, const string & word) {
for ( int i = 0 ; i < sub_num.length(); i ++ )
if ( letter_to_num(word[i]) != sub_num[i] )
return false ;

return true ;
}

int main() {

string number;
vector
< word_index > sorted_index_lv2, sorted_index_lv1;
vector
< word_index > ::iterator it;
int word_amount = 0 , i, j, d, k, word_len, number_len, idx;
int min, min_choice, min_choice_word;

cin
>> number;
while (number != " -1 " ) {
memset(dp, NOT_VALUE,
sizeof (dp));
memset(index_lv1, NOT_VALUE,
sizeof (index_lv1));
sorted_index_lv2.clear();

number_len
= number.length();

cin
>> word_amount;

if ( word_amount == 0 || number_len == 0 ) {
cout
<< " No solution. " << endl;
cin
>> number;
continue ;
}

for ( i = 0 ;i < word_amount;i ++ )
cin
>> words[i];

for ( i = 0 ;i < word_amount;i ++ )
sorted_index_lv2.push_back(make_pair(i, (
int )(words[i].length())));

sort(sorted_index_lv2.begin(), sorted_index_lv2.end(), cmp_index);
// 完成二級(jí)索引

word_len
= sorted_index_lv2[ 0 ].second;
index_lv1[word_len]
= make_pair( 0 , 1 );

for ( i = 1 ; i < sorted_index_lv2.size(); i ++ ) { // 構(gòu)造一級(jí)索引
if ( sorted_index_lv2[i].second != word_len ) {
word_len
= sorted_index_lv2[i].second; // 長(zhǎng)度為舊word_len的單詞沒有了,到新的word_len長(zhǎng)度了
index_lv1[word_len] = make_pair(i, 1 ); // 記錄第一個(gè)長(zhǎng)度為word_len的單詞在sorted_index_lv2中的位置i
}
else {
index_lv1[word_len].second
++ ; // 找到多一個(gè)長(zhǎng)度為word_len的單詞
}
}

dp[
0 ].min_word_amount = 0 ;
for ( i = 1 ;i <= number_len;i ++ ) {

for ( k = 0 , min_choice = - 1 ; k < i; k ++ ) {
if ( dp[k].min_word_amount == NOT_VALUE ) // 沒有長(zhǎng)k的匹配前綴,就算后面有長(zhǎng)i-k的匹配后綴,也沒用
continue ;

idx
= index_lv1[i - k].first; // 獲取后綴長(zhǎng)度的單詞組的一級(jí)索引

if ( idx == NOT_VALUE ) // 沒有長(zhǎng)度為k的單詞
continue ;

// 遍歷所有長(zhǎng)度為i的單詞
for ( j = idx, d = 0 ; d < index_lv1[i - k].second; d ++ , j ++ ) { // second保存的是,在二級(jí)索引中,有多少個(gè)索引項(xiàng)的單詞是長(zhǎng)度為i-k的。

if ( dp[i].min_word_amount == NOT_VALUE || dp[i].min_word_amount > dp[k].min_word_amount + 1 ) { // 當(dāng)k=0時(shí),計(jì)算對(duì)象的就是后綴長(zhǎng)度為i的單詞

if ( match(number.substr(k, i - k), words[sorted_index_lv2[j].first]) ) { // 判斷長(zhǎng)度為i-k的單詞是否符合號(hào)碼的相應(yīng)部分
dp[i].min_word_amount = dp[k].min_word_amount + 1 ;
min_choice
= k;
min_choice_word
= sorted_index_lv2[j].first;
break ; // 同一長(zhǎng)度的單詞,選第一個(gè)能匹配的就夠
}
}
}
}

if ( dp[i].min_word_amount != NOT_VALUE ) { // 長(zhǎng)度為i的前綴串擁有最短匹配單詞組

if ( dp[min_choice].min_word_amount > 0 )
memcpy(dp[i].min_word_seq, dp[min_choice].min_word_seq,
sizeof ( int ) * dp[min_choice].min_word_amount); // 不用擔(dān)心最初序列長(zhǎng)度是0,因?yàn)槭裁炊疾粡?fù)制 ^_^

dp[i].min_word_seq[ dp[i].min_word_amount
- 1 ] = min_choice_word;
}
}

if ( dp[number_len].min_word_amount == NOT_VALUE ) {
cout
<< " No solution. " << endl;
}
else {
for ( i = 0 ; i < dp[number_len].min_word_amount - 1 ; i ++ )
cout
<< words[ dp[number_len].min_word_seq[i] ] << " " ;
cout
<< words[ dp[number_len].min_word_seq[i] ] << endl;
}

cin
>> number;
}

return 0 ;
}

情結(jié)的一題,從大一開始就一直想AC,但一直做到大一尾聲也做不出來,相隔3年了,昨晚就隨便15分鐘想出了算法。

DP的情況是比較簡(jiǎn)單的,只是如何操縱字符串有點(diǎn)難度,通過建立2級(jí)的索引,可以用過長(zhǎng)度來索引到所有擁有該長(zhǎng)度的單詞,最后就剩下個(gè)DP的過程。

Timus 1002


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論