把电话号码转换成为词典中能够记忆的的单词的组合,找到最短的组合。

我这道题应用到的知识点:

1 Trie数据结构

2 map的应用

3 动态规划法Word Break的知识

4 递归剪枝法

思路:

1 建立Trie字典树。方便查找, 可是字典树不是使用字符来建立的。而是把字符转换成数字。建立一个数字字典树。 然后叶子节点设置一个容器vector<string>装原单词。

2 动态规划建立一个表,记录能够在字典树中找到的字符串的前缀子串

3 假设找到整个串都在字典树中,那么就能够直接返回这个单词。假设无法直接找到。那么就要在表中找到一个前缀子串,然后后面部分在字典树中查找,看是否找到包括这个子串的单词,而且要求找到的单词长度最短。- 这里能够使用剪枝法提高效率。

原题:http://acm.timus.ru/problem.aspx?space=1&num=1002

作者:靖心 - http://blog.csdn.net/kenden23

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <unordered_map> using namespace std; class PhoneNumber1002_2
{
static const int SIZE = 10;
struct Node
{
vector<string> words;
Node *children[SIZE];
explicit Node () : words()
{
for (int i = 0; i < SIZE; i++)
{
children[i] = NULL;
}
}
}; struct Trie
{
Node *emRoot;
int count;
explicit Trie(int c = 0) : count(c)
{
emRoot = new Node;
}
~Trie()
{
deleteTrie(emRoot);
}
void deleteTrie(Node *root)
{
if (root)
{
for (int i = 0; i < SIZE; i++)
{
deleteTrie(root->children[i]);
}
delete root;
root = NULL;
}
}
}; void insert(Trie *trie, string &keys, string &keyWords)
{
int len = (int)keys.size(); Node *pCrawl = trie->emRoot;
trie->count++; for (int i = 0; i < len; i++)
{
int k = keys[i] - '0';
if (!pCrawl->children[k])
{
pCrawl->children[k] = new Node;
}
pCrawl = pCrawl->children[k];
}
pCrawl->words.push_back(keyWords);
} Node *search(Node *root, string &keys)
{
int len = (int)keys.size(); Node *pCrawl = root;
for (int i = 0; i < len; i++)
{
int k = keys[i] - '0';
if (!pCrawl->children[k])
{
return NULL;//没走全然部keys
}
pCrawl = pCrawl->children[k];
}
return pCrawl;
} void searchLeft(Node *leaf, Node *r, int len, int &prun)
{
if (len >= prun) return; if (leaf->words.size())
{
r = leaf;
prun = len;
return;
} for (int i = 0; i < SIZE; i++)
{
searchLeft(leaf->children[i], r, len+1, prun);
}
} void wordsToKey(string &keys, string &keyWords,
unordered_map<char, char> &umCC)
{
for (int i = 0; i < (int)keyWords.size(); i++)
{
keys.push_back(umCC[keyWords[i]]);
}
} void charsToMap(const string phdig[], unordered_map<char, char> &umCC)
{
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < (int)phdig[i].size(); k++)
{
umCC[phdig[i][k]] = i + '0';
}
}
} string searchComb(Trie *trie, string &num)
{
vector<string> tbl(num.size());
for (int i = 0; i < (int)num.size(); i++)
{
string s = num.substr(0, i+1);
Node *n = search(trie->emRoot, s);
if (n && n->words.size())
{
tbl[i].append(n->words[0]);
continue;//这里错误写成break! 。
}
for (int j = 1; j <= i; j++)
{
if (tbl[j-1].size())
{
s = num.substr(j, i-j+1);
n = search(trie->emRoot, s);
if (n && n->words.size())
{
tbl[i].append(tbl[j-1]);
tbl[i].append(" ");
tbl[i].append(n->words[0]);
break;
}
}
}
} if (tbl.back().size())
{
return tbl.back();
} string ans;
for (int i = 0; i < (int)tbl.size() - 1; i++)
{
if (tbl[i].size())
{
string tmp = tbl[i];
string keys = num.substr(i+1);
Node *n = search(trie->emRoot, keys); if (!n) continue; Node *r = NULL;
int prun = INT_MAX;
searchLeft(n, r, 0, prun); tmp += r->words[0]; if (ans.empty() || tmp.size() < ans.size())
{
ans = tmp;
}
}
}
return ans.empty()? "No solution." : ans;
} //測试函数。不使用解题
void printTrie(Node *n)
{
if (n)
{
for (int i = 0; i < SIZE; i++)
{
printTrie(n->children[i]);
for (int j = 0; j < (int)n->words.size(); j++)
{
cout<<n->words[j]<<endl;
}
}
}
}
public:
PhoneNumber1002_2()
{
const string phdig[10] =
{"oqz","ij","abc","def","gh","kl","mn","prs","tuv","wxy"};
unordered_map<char, char> umCC;
charsToMap(phdig, umCC); int N; string num, keys, keyWords;
while ((cin>>num) && "-1" != num)
{
cin>>N; Trie trie;
while (N--)
{
cin>>keyWords;
wordsToKey(keys, keyWords, umCC); insert(&trie, keys, keyWords); keys.clear();//别忘记清空
} cout<<searchComb(&trie, num)<<endl;
}
}
};

Timus : 1002. Phone Numbers 题解的更多相关文章

  1. 1002 Phone Numbers 解题报告

    1002. Phone Numbers Time limit: 2.0 secondMemory limit: 64 MB In the present world you frequently me ...

  2. URAL 1002 Phone Numbers(KMP+最短路orDP)

    In the present world you frequently meet a lot of call numbers and they are going to be longer and l ...

  3. CF55D Beautiful numbers 题解

    题目 Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer n ...

  4. Hdoj 1905.Pseudoprime numbers 题解

    Problem Description Fermat's theorem states that for any prime number p and for any integer a > 1 ...

  5. Hdoj 1058.Humble Numbers 题解

    Problem Description A number whose only prime factors are 2,3,5 or 7 is called a humble number. The ...

  6. [LeetCode] Add Two Numbers题解

    Add Two Numbers: You are given two non-empty linked lists representing two non-negative integers. Th ...

  7. poj 1995 Raising Modulo Numbers 题解

    Raising Modulo Numbers Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6347   Accepted: ...

  8. Timus 1009. K-based Numbers

    1009. K-based Numbers Time limit: 0.5 secondMemory limit: 64 MB Let’s consider K-based numbers, cont ...

  9. Timus 1712. Cipher Grille 题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/.未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

随机推荐

  1. Excel的数据批量替换

    该篇文章照抄自:http://www.cnblogs.com/xwgli/p/5845317.html 在 Excel 中使用正则表达式进行查找与替换  在 Excel 中,使用 Alt+F11 快捷 ...

  2. angular2多组件通信流程图

    知识点1:组件属性的双向绑定,需要在属性+Change 作为Output方法返回即可. 知识点2:更新子组件的值,不会引起output触发,父组件不会更新绑定的值 知识点3:属性的双向绑定,只会子组件 ...

  3. sql执行效率 Explain

    explain+sql语句 explain返回的结果项很多,这里我们只关注三种,分别是type,key,rows. key:显示MySQL实际决定使用的键(索引).如果没有选择索引,键是NULL. r ...

  4. Java给各个方法记录执行时间

    Java给各个方法记录执行时间 long startTime = System.currentTimeMillis();...//要测试时间的方法LoggerFactory.getLogger(Bas ...

  5. Threadlocal_笔记

    参考:https://www.jianshu.com/p/377bb840802f https://www.cnblogs.com/dreamroute/p/5034726.html ThreadLo ...

  6. 利用jQuery无缝滚动插件liMarquee实现图片(链接)和文字(链接)向右无缝滚动(兼容ie7+)

    像新闻类的版块经常要求一条条的新闻滚动出现,要实现这种效果,可以使用jQuery无缝滚动插件liMarquee. 注意: 1. 它的兼容性是IE7+,及现代浏览器. 2. 引用的jquery的版本最好 ...

  7. [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划

    [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划 试题描述 一个餐厅在相继的 \(N\) 天里,第 \(i\) 天需要 \(R_i\) 块餐巾 \((i=l,2,-,N)\) ...

  8. [luogu2044][NOI2012] 随机数生成器 [矩阵快速幂]

    题面: 传送门 思路: 看一眼这个公式: $x\left[n+1\right]=\left(a\ast x\left[n\right]+c\right) mod m$ 递推,数据范围$n\leq 10 ...

  9. Windows地址空间

    虚拟地址空间 ​ 当处理器读取或写入存储器位置时,它使用虚拟地址.作为读或写操作的一部分,处理器将虚拟地址转换为物理地址.通过虚拟地址访问内存具有以下优势: 程序可以使用连续范围的虚拟地址来访问在物理 ...

  10. [LeetCode] Gas Station 贪心

    There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You ...