第1题:字符串插入
有两个字符串str和substr,str的字符个数不超过10,substr的字符个数为3。(字符个数不包括字符串结尾处的'\0'。)将substr插入到str中ASCII码最大的那个字符后面,若有多个最大则只考虑第一个。
时间限制:1000
内存限制:65536
输入输入包括若干行,每一行为一组测试数据,格式为 str substr
输出对于每一组测试数据,输出插入之后的字符串。
样例输入abcab eee
12343 555
样例输出abceeeab
12345553
下面是使用C语言编写的示例代码,实现将substr插入到str中ASCII码最大的字符后面:
c
#include <stdio.h>
#include <string.h>
void insertSubstring(char *str, const char *substr) {
int maxIndex = 0;
int maxAscii = str[0];
// 找到ASCII码最大的字符的索引
for (int i = 1; str[i] != '\0'; i++) {
if (str[i] > maxAscii) {
maxAscii = str[i];
maxIndex = i;
}
}
// 在最大字符后面插入substr
int strLen = strlen(str);
int substrLen = strlen(substr);
for (int i = strLen; i > maxIndex + 1; i--) {
str[i + substrLen] = str[i];
}
for (int i = 0; i < substrLen; i++) {
str[maxIndex + 1 + i] = substr[i];
}
}
int main() {
char str[11];
char substr[4];
while (scanf("%s %s", str, substr) != EOF) {
insertSubstring(str, substr);
printf("%s\n", str);
}
return 0;
}
代码中的insertSubstring
函数用于将substr插入到str中ASCII码最大的字符后面。它首先遍历str找到ASCII码最大的字符的索引,然后将substr插入到该索引后面。插入操作分两步:首先将原来的字符依次向后移动,然后将substr插入到空出的位置。
在main
函数中,我们使用scanf
读取输入的每一组测试数据,然后调用insertSubstring
函数进行处理,并输出结果。
第2题:机器翻译
VariantF的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。
假设内存中有M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。
时间限制:1000
内存限制:262144
输入第一行为两个正整数M 和N,代表内存容量和文章的长度。 第二行为N 个非负整数,按照文章的顺序,每个数(大小不超过1000000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。 对于50%的数据,1<=N、M<=1000; 对于100%的数据,1<=N、M<=1000000。
输出一个整数,为软件需要查词典的次数。
样例输入3 7
1 2 1 5 4 4 1
样例输出5
提示整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况: 空:内存初始状态为空。 1. 1:查找单词1 并调入内存。 2. 1 2:查找单词2 并调入内存。 3. 1 2:在内存中找到单词1。 4. 1 2 5:查找单词5 并调入内存。 5. 2 5 4:查找单词4 并调入内存替代单词1。 6. 2 5 4:在内存中找到单词4。 7. 5 4 1:查找单词1 并调入内存替代单词2。 共计查了5 次词典。
下面是使用C语言编写的示例代码,实现计算翻译软件需要查词典的次数:
c
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int word;
int translation;
} MemoryUnit;
int main() {
int M, N;
scanf("%d %d", &M, &N);
int* words = (int*)malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {
scanf("%d", &words[i]);
}
MemoryUnit* memory = (MemoryUnit*)malloc(M * sizeof(MemoryUnit));
int memoryCount = 0;
int dictionaryCount = 0;
for (int i = 0; i < N; i++) {
int currentWord = words[i];
int found = 0;
for (int j = 0; j < memoryCount; j++) {
if (memory[j].word == currentWord) {
found = 1;
break;
}
}
if (!found) {
if (memoryCount < M) {
memory[memoryCount].word = currentWord;
memory[memoryCount].translation = 0;
memoryCount++;
} else {
memory[0].word = currentWord;
memory[0].translation = 0;
dictionaryCount++;
}
}
}
printf("%d\n", dictionaryCount);
free(words);
free(memory);
return 0;
}
代码中,我们使用动态数组words
保存待翻译文章中的单词,使用动态数组memory
保存内存中的词典单元。memory
数组的每个元素是一个MemoryUnit
结构体,包含word
和translation
字段,分别表示单词和译义。
我们使用memoryCount
变量记录当前内存中已存入的单词数,使用dictionaryCount
变量记录查词典的次数。
对于每个待翻译的单词,我们遍历内存中的词典单元,检查是否存在该单词,如果找到则表示无需查词典,如果未找到则需要进行查词典的操作。
当内存未满时,我们将新单词存入一个未使用的内存单元,并增加memoryCount
;当内存已满时,我们将最早进入内存的单词替换为新单词,并增加dictionaryCount
。
最后,我们输出dictionaryCount
作为结果,表示翻译软件需要查词典的次数。
第3题:栈基本操作
依次读入序列元素1,2,...,n进栈,每进一个元素,机器可要求下一个元素进栈或弹栈,如此进行。给定一个输入序列,判断栈空时弹出的元素构成的序列是否可能等于给定的序列,如果是则输出栈的操作过程,否则输出"NO"。
时间限制:1000
内存限制:65535
输入输入分两行 第一行为n的值(即序列元素个数) 第二行为给定的输入序列(序列元素均为整型)
输出如果输入序列能够由题目规定的操作得到,则输出对栈的操作过程 否则直接输出"NO"
样例输入7
4 5 3 6 2 7 1
样例输出PUSH 1
PUSH 2
PUSH 3
PUSH 4
POP 4
PUSH 5
POP 5
POP 3
PUSH 6
POP 6
POP 2
PUSH 7
POP 7
POP 1
提示给定序列中有可能有不在1...n之间的数字
下面是使用C语言编写的示例代码,实现栈的基本操作和判断输入序列是否可以通过栈操作得到:
c
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int* elements;
int top;
} Stack;
void initStack(Stack* stack, int size) {
stack->elements = (int*)malloc(size * sizeof(int));
stack->top = -1;
}
void push(Stack* stack, int element) {
stack->top++;
stack->elements[stack->top] = element;
}
int pop(Stack* stack) {
int element = stack->elements[stack->top];
stack->top--;
return element;
}
int main() {
int n;
scanf("%d", &n);
int* sequence = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
scanf("%d", &sequence[i]);
}
Stack stack;
initStack(&stack, n);
int current = 1;
int sequenceIndex = 0;
int possible = 1;
while (sequenceIndex < n) {
if (stack.top >= 0 && stack.elements[stack.top] == sequence[sequenceIndex]) {
pop(&stack);
printf("POP %d\n", sequence[sequenceIndex]);
sequenceIndex++;
} else if (current <= n) {
push(&stack, current);
printf("PUSH %d\n", current);
current++;
} else {
possible = 0;
break;
}
}
if (possible) {
printf("YES\n");
} else {
printf("NO\n");
}
free(sequence);
free(stack.elements);
return 0;
}
代码中,我们使用Stack
结构体表示栈,其中elements
是一个动态数组,用于保存栈中的元素,top
表示栈顶的索引。
initStack
函数用于初始化栈,分配内存并将栈顶初始化为-1。
push
函数用于将元素压入栈中,栈顶指针加1,并将元素存入栈顶位置。
pop
函数用于弹出栈顶的元素,返回栈顶元素的值,并将栈顶指针减1。
在main
函数中,我们首先读入输入序列,并初始化一个大小为n的栈。
然后,我们使用current
变量表示下一个要进栈的元素,使用sequenceIndex
变量表示输入序列的当前位置,使用possible
变量表示输入序列是否可由栈操作得到。
我们使用循环对输入序列进行处理,判断栈顶元素和当前输入序列位置的元素是否相等,如果相等,则执行弹栈操作,并将sequenceIndex
加1;如果不相等,则执行压栈操作,并将current
加1。
如果栈操作结束后,输入序列已全部处理完毕(sequenceIndex
等于n),则说明输入序列可以由栈操作得到,将possible
设为1;否则,将possible
设为0。
最后,根据possible
的值输出结果。如果输入序列可由栈操作得到,则输出栈的操作过程,否则输出"NO"。
第4题:双端队列
定义一个双端队列,进队操作与普通队列一样,从队尾进入。出队操作既可以从队头,也可以从队尾。编程实现这个数据结构。
时间限制:1000
内存限制:65535
输入第一行输入一个整数t,代表测试数据的组数。 每组数据的第一行输入一个整数n,表示操作的次数。 接着输入n行,每行对应一个操作,首先输入一个整数type。 当type=1,进队操作,接着输入一个整数x,表示进入队列的元素。 当type=2,出队操作,接着输入一个整数c,c=0代表从队头出队,c=1代表从队尾出队。 n <= 1000
输出对于每组测试数据,输出执行完所有的操作后队列中剩余的元素,元素之间用空格隔开,按队头到队尾的顺序输出,占一行。如果队列中已经没有任何的元素,输出NULL。
样例输入2
5
1 2
1 3
1 4
2 0
2 1
6
1 1
1 2
1 3
2 0
2 1
2 0
样例输出3
NULL
下面是一个使用C语言编写的双端队列的实现,满足题目的要求:
c
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1000
typedef struct {
int data[MAX_SIZE];
int front; // 队头指针
int rear; // 队尾指针
} Deque;
void initDeque(Deque* deque) {
deque->front = -1; // 初始化队头指针为-1
deque->rear = -1; // 初始化队尾指针为-1
}
int isDequeEmpty(Deque* deque) {
return deque->front == -1; // 如果队头指针为-1,表示队列为空
}
int isDequeFull(Deque* deque) {
return (deque->front == 0 && deque->rear == MAX_SIZE - 1) || (deque->front == deque->rear + 1);
// 如果队头指针在队尾指针之前一个位置,或者队头指针在队尾指针之后一个位置,表示队列已满
}
void enqueueFront(Deque* deque, int x) {
if (isDequeFull(deque)) {
printf("Deque is full. Cannot enqueue.\n");
return;
}
if (deque->front == -1) {
deque->front = 0;
deque->rear = 0;
} else if (deque->front == 0) {
deque->front = MAX_SIZE - 1;
} else {
deque->front--;
}
deque->data[deque->front] = x; // 将元素放入队头位置
}
void enqueueRear(Deque* deque, int x) {
if (isDequeFull(deque)) {
printf("Deque is full. Cannot enqueue.\n");
return;
}
if (deque->front == -1) {
deque->front = 0;
deque->rear = 0;
} else if (deque->rear == MAX_SIZE - 1) {
deque->rear = 0;
} else {
deque->rear++;
}
deque->data[deque->rear] = x; // 将元素放入队尾位置
}
int dequeueFront(Deque* deque) {
if (isDequeEmpty(deque)) {
printf("Deque is empty. Cannot dequeue.\n");
return -1;
}
int x = deque->data[deque->front]; // 获取队头元素的值
if (deque->front == deque->rear) {
deque->front = -1; // 如果队列中只有一个元素,出队后将队头指针重置为-1
deque->rear = -1; // 如果队列中只有一个元素,出队后将队尾指针重置为-1
} else if (deque->front == MAX_SIZE - 1) {
deque->front = 0; // 如果队头指针在队尾指针之前一个位置,出队后将队头指针移到队头位置
} else {
deque->front++; // 队头指针向后移动一位
}
return x; // 返回出队的元素值
}
int dequeueRear(Deque* deque) {
if (isDequeEmpty(deque)) {
printf("Deque is empty. Cannot dequeue.\n");
return -1;
}
int x = deque->data[deque->rear]; // 获取队尾元素的值
if (deque->front == deque->rear) {
deque->front = -1; // 如果队列中只有一个元素,出队后将队头指针重置为-1
deque->rear = -1; // 如果队列中只有一个元素,出队后将队尾指针重置为-1
} else if (deque->rear == 0) {
deque->rear = MAX_SIZE - 1; // 如果队尾指针在队头指针之后一个位置,出队后将队尾指针移到队尾位置
} else {
deque->rear--; // 队尾指针向前移动一位
}
return x; // 返回出队的元素值
}
void printDeque(Deque* deque) {
if (isDequeEmpty(deque)) {
printf("NULL\n");
return;
}
int i;
if (deque->front <= deque->rear) {
for (i = deque->front; i <= deque->rear; i++) {
printf("%d ", deque->data[i]);
}
} else {
for (i = deque->front; i < MAX_SIZE; i++) {
printf("%d ", deque->data[i]);
}
for (i = 0; i <= deque->rear; i++) {
printf("%d ", deque->data[i]);
}
}
printf("\n");
}
int main() {
int t, n, i, type, x, c;
scanf("%d", &t);
while (t--) {
Deque deque;
initDeque(&deque);
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%d", &type);
if (type == 1) {
scanf("%d", &x);
enqueueRear(&deque, x);
} else if (type == 2) {
scanf("%d", &c);
if (c == 0) {
dequeueFront(&deque);
} else if (c == 1) {
dequeueRear(&deque);
}
}
}
printDeque(&deque);
}
return 0;
}
这个程序定义了一个双端队列的数据结构,并实现了进队和出队的操作。在主函数中,首先读取测试数据的组数t,然后对于每组数据,读取操作的次数n。接下来,根据操作类型进行进队或出队操作,最后打印队列中剩余的元素。
请注意,这个程序假设输入的数据是有效的,即不会出现在空队列中进行出队操作的情况。在实际应用中,可能需要添加更多的错误处理逻辑来确保程序的稳定性。另外,由于题目要求输出的格式是以空格分隔的元素列表,所以在输出时需要注意最后一个元素后面不要输出多余的空格。