P - Shortest Prefixes


Time Limit: 1000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u

[Submit]   [Go Back]   [Status]

Description

A prefix of a string is a substring starting at the beginning of the given string. The prefixes of "carbon" are: "c", "ca", "car", "carb", "carbo", and "carbon". Note that the empty string is not considered a prefix in this problem, but every non-empty string is considered to be a prefix of itself. In everyday language, we tend to abbreviate words by prefixes. For example, "carbohydrate" is commonly abbreviated by "carb". In this problem, given a set of words, you will find for each word the shortest prefix that uniquely identifies the word it represents. 

In the sample input below, "carbohydrate" can be abbreviated to "carboh", but it cannot be abbreviated to "carbo" (or anything shorter) because there are other words in the list that begin with "carbo". 

An exact match will override a prefix match. For example, the prefix "car" matches the given word "car" exactly. Therefore, it is understood without ambiguity that "car" is an abbreviation for "car" , not for "carriage" or any of the other words in the list that begins with "car". 

Input

The input contains at least two, but no more than 1000 lines. Each line contains one word consisting of 1 to 20 lower case letters.

Output

The output contains the same number of lines as the input. Each line of the output contains the word from the corresponding line of the input, followed by one blank space, and the shortest prefix that uniquely (without ambiguity) identifies this word.

Sample Input

carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate

Sample Output

carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona
帮我详细解释这些代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // 最大节点数量(房间总数估算) #define MAX_NODES 50 // 房间名称最大长度 #define NAME_LEN 10 // 全局变量控制是否开启调试模式 bool debug_mode = false; // 图的邻接表表示:每个房间可以到达的其他房间 typedef struct Node { char name[NAME_LEN]; struct Node* next; } Node; typedef struct Graph { Node* vertices[MAX_NODES]; int num_vertices; char vertex_names[MAX_NODES][NAME_LEN]; // 存储所有顶点名字便于查找索引 } Graph; // 队列用于BFS typedef struct Queue { int items[MAX_NODES]; int front; int rear; } Queue; // 栈用于DFS typedef struct Stack { int items[MAX_NODES]; int top; } Stack; // 函数声明 Graph* create_graph(); int add_vertex(Graph* g, const char* name); Node* create_node(const char* name); void add_edge(Graph* g, const char* from, const char* to); Queue* create_queue(); void enqueue(Queue* q, int index); int dequeue(Queue* q); bool is_empty_queue(Queue* q); Stack* create_stack(); void push(Stack* s, int index); int pop(Stack* s); bool is_empty_stack(Stack* s); int find_index(Graph* g, const char* name); void print_path(int parent[], int indexes[], int n, Graph* g); void bfs(Graph* g, int start_idx); void dfs(Graph* g, int start_idx); // 创建图 Graph* create_graph() { Graph* g = (Graph*)malloc(sizeof(Graph)); for (int i = 0; i < MAX_NODES; i++) { g->vertices[i] = NULL; } g->num_vertices = 0; return g; } // 添加新顶点并返回其索引 int add_vertex(Graph* g, const char* name) { for (int i = 0; i < g->num_vertices; i++) { if (strcmp(g->vertex_names[i], name) == 0) { return i; } } strcpy(g->vertex_names[g->num_vertices], name); g->vertices[g->num_vertices] = NULL; return g->num_vertices++; } // 创建邻接节点 Node* create_node(const char* name) { Node* node = (Node*)malloc(sizeof(Node)); strcpy(node->name, name); node->next = NULL; return node; } // 添加无向边 void add_edge(Graph* g, const char* from, const char* to) { int from_idx = find_index(g, from); int to_idx = find_index(g, to); Node* newNode = create_node(to); newNode->next = g->vertices[from_idx]; g->vertices[from_idx] = newNode; newNode = create_node(from); newNode->next = g->vertices[to_idx]; g->vertices[to_idx] = newNode; if (debug_mode) printf("Added edge: %s <-> %s\n", from, to); } // 查找顶点索引 int find_index(Graph* g, const char* name) { for (int i = 0; i < g->num_vertices; i++) { if (strcmp(g->vertex_names[i], name) == 0) { return i; } } return -1; // 不应该发生 } // 创建队列 Queue* create_queue() { Queue* q = (Queue*)malloc(sizeof(Queue)); q->front = -1; q->rear = -1; return q; } // 入队 void enqueue(Queue* q, int index) { if (q->rear == MAX_NODES - 1) { printf("Queue full!\n"); } else { if (q->front == -1) q->front = 0; q->rear++; q->items[q->rear] = index; } } // 出队 int dequeue(Queue* q) { int item; if (is_empty_queue(q)) { return -1; } else { item = q->items[q->front]; q->front++; if (q->front > q->rear) { q->front = q->rear = -1; } } return item; } // 判断队列为空 bool is_empty_queue(Queue* q) { return q->front == -1; } // 创建栈 Stack* create_stack() { Stack* s = (Stack*)malloc(sizeof(Stack)); s->top = -1; return s; } // 压栈 void push(Stack* s, int index) { if (s->top == MAX_NODES - 1) { printf("Stack overflow!\n"); } else { s->items[++s->top] = index; } } // 弹栈 int pop(Stack* s) { if (is_empty_stack(s)) { return -1; } else { return s->items[s->top--]; } } // 判断栈为空 bool is_empty_stack(Stack* s) { return s->top == -1; } // 打印路径 void print_path(int parent[], int indexes[], int goal_idx, Graph* g) { int path[MAX_NODES]; int path_len = 0; int current = goal_idx; while (current != -1) { path[path_len++] = current; current = parent[current]; } printf("Solution Path: "); for (int i = path_len - 1; i >= 0; i--) { printf("%s", g->vertex_names[path[i]]); if (i > 0) printf(" -> "); } printf("\n"); } // 广度优先搜索 void bfs(Graph* g, int start_idx) { bool visited[MAX_NODES] = {false}; int parent[MAX_NODES]; Queue* q = create_queue(); for (int i = 0; i < g->num_vertices; i++) parent[i] = -1; visited[start_idx] = true; enqueue(q, start_idx); if (debug_mode) printf("BFS started from %s\n", g->vertex_names[start_idx]); while (!is_empty_queue(q)) { int current_idx = dequeue(q); char* current_name = g->vertex_names[current_idx]; if (debug_mode) printf("Exploring: %s\n", current_name); // 目标检查:当前是否在 "Charger" if (strcmp(current_name, "Charger") == 0) { printf("Goal found!\n"); print_path(parent, NULL, current_idx, g); free(q); return; } // 遍历邻居 Node* neighbor = g->vertices[current_idx]; while (neighbor != NULL) { int neighbor_idx = find_index(g, neighbor->name); if (!visited[neighbor_idx]) { visited[neighbor_idx] = true; parent[neighbor_idx] = current_idx; enqueue(q, neighbor_idx); if (debug_mode) printf("Enqueued: %s (from %s)\n", neighbor->name, current_name); } neighbor = neighbor->next; } } printf("No path found to Charger.\n"); free(q); } // 深度优先搜索 void dfs(Graph* g, int start_idx) { bool visited[MAX_NODES] = {false}; int parent[MAX_NODES]; Stack* s = create_stack(); for (int i = 0; i < g->num_vertices; i++) parent[i] = -1; push(s, start_idx); if (debug_mode) printf("DFS started from %s\n", g->vertex_names[start_idx]); while (!is_empty_stack(s)) { int current_idx = pop(s); if (visited[current_idx]) continue; visited[current_idx] = true; char* current_name = g->vertex_names[current_idx]; if (debug_mode) printf("Exploring: %s\n", current_name); // 目标检查 if (strcmp(current_name, "Charger") == 0) { printf("Goal found!\n"); print_path(parent, NULL, current_idx, g); free(s); return; } // 将未访问的邻居压入栈(逆序保证顺序) Node* temp = g->vertices[current_idx]; Node* neighbors[MAX_NODES]; int count = 0; while (temp != NULL) { int idx = find_index(g, temp->name); if (!visited[idx]) { neighbors[count++] = temp; } temp = temp->next; } // 逆序入栈以保持字母顺序探索(可选) for (int i = count - 1; i >= 0; i--) { int idx = find_index(g, neighbors[i]->name); if (!visited[idx]) { parent[idx] = current_idx; push(s, idx); if (debug_mode) printf("Pushed: %s (from %s)\n", neighbors[i]->name, current_name); } } } printf("No path found to Charger.\n"); free(s); } // 构建建筑地图 Graph* build_map() { Graph* g = create_graph(); // 各楼层房间定义 const char* floors[] = {"1", "2", "3"}; const char* prefixes[] = {"A", "B", "C", "D", "E", "F", "G", "H", "K", "L", "M", "N"}; // 添加所有接待室、办公室、门厅、电梯 for (int f = 0; f < 3; f++) { char floor[2]; sprintf(floor, "%s", floors[f]); // Lobby and Lift char lobby[10], lift[10]; sprintf(lobby, "Lobby_%s", floor); sprintf(lift, "Lift_%s", floor); add_vertex(g, lobby); add_vertex(g, lift); for (int p = 0; p < 4; p++) { char rec[10], off[10]; sprintf(rec, "%s%s.1", prefixes[p], floor); sprintf(off, "%s%s.2", prefixes[p], floor); add_vertex(g, rec); add_vertex(g, off); } } // 充电站 add_vertex(g, "Charger"); // 连接规则 // 1. 接待室 -> 办公室 for (int f = 0; f < 3; f++) { char floor[2]; sprintf(floor, "%s", floors[f]); for (int p = 0; p < 4; p++) { char rec[10], off[10]; sprintf(rec, "%s%s.1", prefixes[p], floor); sprintf(off, "%s%s.2", prefixes[p], floor); add_edge(g, rec, off); } } // 2. 每层接待室 -> 门厅 for (int f = 0; f < 3; f++) { char floor[2]; sprintf(floor, "%s", floors[f]); char lobby[10]; sprintf(lobby, "Lobby_%s", floor); for (int p = 0; p < 4; p++) { char rec[10]; sprintf(rec, "%s%s.1", prefixes[p], floor); add_edge(g, rec, lobby); } } // 3. 门厅 -> 电梯(同层) for (int f = 0; f < 3; f++) { char floor[2]; sprintf(floor, "%s", floors[f]); char lobby[10], lift[10]; sprintf(lobby, "Lobby_%s", floor); sprintf(lift, "Lift_%s", floor); add_edge(g, lobby, lift); } // 4. 电梯上下连接(仅一层差) add_edge(g, "Lift_1", "Lift_2"); add_edge(g, "Lift_2", "Lift_3"); // 5. 地面电梯 → 充电站 add_edge(g, "Lift_1", "Charger"); return g; } // 主函数 int main() { Graph* g = build_map(); char start_location[NAME_LEN]; int choice; printf("=== HOOVI Navigation System ===\n"); // 是否启用调试模式 printf("Enable debug mode? (1=yes, 0=no): "); scanf("%d", &choice); debug_mode = (choice == 1); // 输入起点 printf("Enter starting location (e.g., B3.2, Lift_1, N1.1): "); scanf("%s", start_location); // 验证输入是否存在 int start_idx = find_index(g, start_location); if (start_idx == -1) { printf("Error: Invalid starting location '%s'. Please check spelling.\n", start_location); return 1; } // 选择算法 printf("Choose search method:\n1. BFS (Shortest Path)\n2. DFS\n> "); scanf("%d", &choice); printf("Start Location: %s\n", start_location); printf("Goal Location: Charger\n"); switch (choice) { case 1: bfs(g, start_idx); break; case 2: dfs(g, start_idx); break; default: printf("Invalid choice. Using BFS by default.\n"); bfs(g, start_idx); } return 0; }
最新发布
11-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值