A string can be abbreviated by replacing any number of non-adjacent substrings with their lengths. For example, a string such as "substitution" could be abbreviated as (but not limited to):
"s10n" ("s ubstitutio n")
"sub4u4" ("sub stit u tion")
"12" ("substitution")
"su3i1u2on" ("su bst i t u ti on")
"substitution" (no substrings replaced)
Note that "s55n" ("s ubsti tutio n") is not a valid abbreviation of "substitution" because the replaced substrings are adjacent.
The length of an abbreviation is the number of letters that were not replaced plus the number of substrings that were replaced. For example, the abbreviation "s10n" has a length of 3 (2 letters + 1 substring) and "su3i1u2on" has a length of 9 (6 letters + 3 substrings).
Given a target string target and an array of strings dictionary, return an abbreviation of target with the shortest possible length such that it is not an abbreviation of any string in dictionary. If there are multiple shortest abbreviations, return any of them.
Input & Output
Example 1 — Basic Case
$Input:target = "apple", dictionary = ["blade"]
›Output:"a4"
💡 Note:The abbreviation "a4" (representing "apple") is unique because "blade" cannot be abbreviated to "a4" since it doesn't start with 'a'
The key insight is to generate all possible abbreviations and find the shortest one that doesn't conflict with any dictionary word. Best approach uses bit manipulation to represent abbreviation patterns efficiently. Time: O(2^n × m × k), Space: O(1)
Common Approaches
✓
Bit Manipulation Optimization
⏱️ Time: O(2^n × m × k)
Space: O(1)
Instead of recursive backtracking, use bit manipulation where each bit represents whether to abbreviate that position. This generates abbreviations more efficiently by treating each bit pattern as an abbreviation template.
Generate All Abbreviations
⏱️ Time: O(2^n × m × k)
Space: O(2^n)
Use backtracking to generate all possible abbreviations of the target string. For each abbreviation, check if it conflicts with any word in the dictionary. Return the shortest valid abbreviation.
Bit Manipulation Optimization — Algorithm Steps
Use bit masks from 0 to 2^n-1 to represent abbreviation patterns
For each mask, generate the corresponding abbreviation
Check uniqueness against dictionary and track shortest valid abbreviation
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Bit Pattern
Each bit represents abbreviate/keep decision
2
Generate
Convert bit pattern to abbreviation string
3
Validate
Check uniqueness and track shortest
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LEN 100
#define MAX_DICT 100
#define MAX_CANDIDATES 1000
typedef struct {
char abbrev[MAX_LEN];
int mask;
} Candidate;
static char abbrevStorage[MAX_CANDIDATES][MAX_LEN];
char* generateAbbrev(char* word, int mask) {
static char result[MAX_LEN];
int pos = 0;
int i = 0;
int n = strlen(word);
while (i < n) {
if (mask & (1 << i)) {
int count = 0;
while (i < n && (mask & (1 << i))) {
count++;
i++;
}
pos += sprintf(result + pos, "%d", count);
} else {
result[pos++] = word[i];
i++;
}
}
result[pos] = '\0';
return result;
}
int isAbbreviation(char* abbr, char* word) {
int i = 0, j = 0;
while (i < strlen(abbr) && j < strlen(word)) {
if (isalpha(abbr[i])) {
if (abbr[i] != word[j]) return 0;
i++;
j++;
} else {
if (abbr[i] == '0') return 0;
int num = 0;
while (i < strlen(abbr) && isdigit(abbr[i])) {
num = num * 10 + (abbr[i] - '0');
i++;
}
j += num;
}
}
return i == strlen(abbr) && j == strlen(word);
}
void priority(int mask, int n, int* bits) {
// Convert to binary and reverse to prioritize beginning
for (int i = 0; i < n; i++) {
bits[i] = (mask & (1 << i)) ? 1 : 0;
}
}
int compareCandidates(const void* a, const void* b, void* n_ptr) {
const Candidate* candA = (const Candidate*)a;
const Candidate* candB = (const Candidate*)b;
int n = *(int*)n_ptr;
int bitsA[32], bitsB[32];
priority(candA->mask, n, bitsA);
priority(candB->mask, n, bitsB);
for (int i = 0; i < n; i++) {
if (bitsA[i] != bitsB[i]) {
return bitsA[i] - bitsB[i];
}
}
return 0;
}
void sortCandidates(Candidate* candidates, int count, int n) {
// Simple bubble sort since qsort_r is not portable
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - i - 1; j++) {
int bitsA[32], bitsB[32];
priority(candidates[j].mask, n, bitsA);
priority(candidates[j+1].mask, n, bitsB);
int shouldSwap = 0;
for (int k = 0; k < n; k++) {
if (bitsA[k] < bitsB[k]) {
shouldSwap = 0;
break;
} else if (bitsA[k] > bitsB[k]) {
shouldSwap = 1;
break;
}
}
if (shouldSwap) {
Candidate temp = candidates[j];
candidates[j] = candidates[j+1];
candidates[j+1] = temp;
}
}
}
}
char* solution(char* target, char dictionary[][MAX_LEN], int dict_size) {
int n = strlen(target);
static char result[MAX_LEN];
// Try all possible abbreviations in order of length
for (int target_len = 1; target_len <= n; target_len++) {
static Candidate candidates[MAX_CANDIDATES];
int candidateCount = 0;
for (int mask = 0; mask < (1 << n); mask++) {
char* abbrev = generateAbbrev(target, mask);
if (strlen(abbrev) == target_len) {
strcpy(candidates[candidateCount].abbrev, abbrev);
candidates[candidateCount].mask = mask;
candidateCount++;
}
}
// Sort candidates to prefer keeping characters at the beginning
// We want smaller mask values first, but among same bit count,
// prefer masks where kept bits (0s) are at the beginning
sortCandidates(candidates, candidateCount, n);
for (int c = 0; c < candidateCount; c++) {
char* abbrev = candidates[c].abbrev;
int valid = 1;
for (int i = 0; i < dict_size; i++) {
if (strcmp(dictionary[i], target) != 0 && isAbbreviation(abbrev, dictionary[i])) {
valid = 0;
break;
}
}
if (valid) {
strcpy(result, abbrev);
return result;
}
}
}
strcpy(result, target);
return result;
}
int main() {
char target[MAX_LEN];
static char dictionary[MAX_DICT][MAX_LEN];
int dict_size = 0;
fgets(target, sizeof(target), stdin);
target[strcspn(target, "\n")] = 0;
char line[1000];
fgets(line, sizeof(line), stdin);
if (strcmp(line, "[]\n") != 0) {
const char* p = line;
while (*p && *p != '[') p++;
if (*p == '[') p++;
while (*p && *p != ']' && dict_size < MAX_DICT) {
while (*p && (*p == ' ' || *p == ',' || *p == '"')) p++;
if (*p == ']' || *p == '\0') break;
const char* start = p;
while (*p && *p != '"' && *p != ',' && *p != ']') p++;
int len = p - start;
if (len > 0) {
strncpy(dictionary[dict_size], start, len);
dictionary[dict_size][len] = '\0';
dict_size++;
}
while (*p && *p == '"') p++;
}
}
char* result = solution(target, dictionary, dict_size);
printf("%s\n", result);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(2^n × m × k)
2^n bit patterns to check, each validated against m dictionary words of average length k
n
2n
⚠ Quadratic Growth
Space Complexity
O(1)
Only uses constant extra space for current abbreviation generation
n
2n
✓ Linear Space
28.5K Views
MediumFrequency
~45 minAvg. Time
892 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.