Problem
As a follow up for Tiny URL, we are going to support custom tiny url, so that user can create their own tiny url.
Solution
class TinyUrl2 {
private:
const long long hashSize = 62 ^ 6;
map<long long, string> id2long;
map<string, long long> long2id;
const string tinyHeader = "http://tiny.url/";
map<string, string> custom2long;
map<string, string> long2custom;
public:
/**
* @param long_url a long url
* @param a short key
* @return a short url starts with http://tiny.url/
*/
string createCustom(string& long_url, string& short_key) {
string tinyURL = tinyHeader + short_key;
if (custom2long.count(short_key) > 0) {
if (custom2long[short_key] == long_url) {
return tinyURL;
} else {
return "error";
}
}
if (long2custom.count(long_url) > 0) {
if (long2custom[long_url] == short_key) {
return tinyURL;
} else {
return "error";
}
}
long long id = shortURL2id(short_key);
if (id2long.count(id) > 0) {
if (id2long[id] == long_url) {
return tinyURL;
} else {
return "error";
}
}
custom2long[short_key] = long_url;
long2custom[long_url] = short_key;
return tinyURL;
}
char number2char(int n) {
if (n <= 9) {
return '0' + n;
} else if (n <= 35) {
return 'a' + (n - 10);
} else {
return 'A' + (n - 36);
}
}
long long char2number(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
} else if ('a' <= c && c <= 'z') {
return c - 'a' + 10;
} else if ('A' <= c && c <= 'Z') {
return c - 'A' + 36;
}
return 0;
}
long long shortURL2id(string url) {
long long id = 0;
for(int i = 0; i < url.size(); i++) {
id = id * 62 + char2number(url[i]);
}
return id;
}
string longToShort(string& url) {
if (long2custom.count(url) > 0) {
return tinyHeader + long2custom[url];
}
long long number = 0;
for(int i = 0; i < url.size(); i++) {
number = (number * 256 + (long long)url[i]) % hashSize;
}
while (id2long.count(number) > 0 && id2long[number] != url) {
number++;
}
id2long[number] = url;
string shortURL;
while (number > 0) {
int mod = number % 62;
number /= 62;
//shortURL = number2char(mod) + shortURL;
shortURL.push_back(number2char(mod));
}
while (shortURL.size() < 6) {
// shortURL = "0" + shortURL;
shortURL.push_back('0');
}
reverse(shortURL.begin(), shortURL.end());
shortURL = tinyHeader + shortURL;
return shortURL;
}
/**
* @param url a short url starts with http://tiny.url/
* @return a long url
*/
string shortToLong(string& url) {
string urlWithoutHeader = url.substr(tinyHeader.size(), url.size());
int id = shortURL2id(urlWithoutHeader);
if (id2long.count(id) > 0) {
return id2long[id];
}
if (custom2long.count(urlWithoutHeader) > 0) {
return custom2long[urlWithoutHeader];
}
return "";
}
};