题目
Description
给定n个括号序列,两两配对,问最多能组成多少对合法括号序列。(每一个括号序列只能在一对中出现)
Input
第一行输入整数 表示有 n个括号序列。
接下来 n行,每行输入一个只由“(”和”)“构成的字符串Si 。(字符串长度满足1<|Si|<1e5)
Output
输出一个整数,表示最大的合法括号序列对数。
相关内容我也放在了以下链接,便于您更好的观看
详细描述
代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef long long int lli;
typedef struct Str{
char arr[200000];
lli left;
lli right;
struct Str *next;
}str;
//基本思路:使用链表储存字符串,链表为空时往里插结点,否则就用新的信息与链表内各节点比较
//先判断左右括号合起来是否相等(不等则肯定不成立)
//然后将两个字符串拼接(有两个顺序都要考虑)存左括号,遇到右括号弹出;
lli getl(char a[]){
lli result=0;
for(int i=0;i<strlen(a);i++){
if(a[i]=='('){
result++;
}
}
return result;
}
lli getr(char a[]){
lli result=0;
for(int i=0;i<strlen(a);i++){
if(a[i]==')'){
result++;
}
}
return result;
}
void reset(str *head,str *p){//重置尾结点
p=head;
while(p->next!=NULL){
p=p->next;
}
}
void getout(str *head,str *p){//脱开某个结点
str *q=head;
while(q->next!=p){
q=q->next;
}//停在q->next=p这,即q为p前一节点
q->next=p->next;
free(p);
}
int main(){
lli result=0;
lli n=0;
scanf("%lld",&n);
getchar();//吃空格
//头指针
str *head=(str*)malloc(sizeof(str));
head->next=NULL;
str *tail=head;//尾结点
//读入后续结点
for(lli i=1;i<=n;i++){
//前置处理
str *curr=(str*)malloc(sizeof(str));
gets(curr->arr);
curr->left=getl(curr->arr);
curr->right=getr(curr->arr);
//对于可能为第一个结点而言
if(tail==head){//如果尾结点为头结点
head->next=curr;
curr->next=NULL;
tail=tail->next;//尾结点指向curr
}
else{
str *place=head->next;//走链表的指针
int pp=0;//匹配状态
while(place!=NULL){//脱出条件:走完全链表
if(place->left+curr->left!=place->right+curr->right){//括号数量不匹配
place=place->next;
}
else{//括号匹配
char *cfront=strcat(curr->arr,place->arr);
lli lbox=0;
int status=1;
for(lli i=0;i<strlen(cfront);i++){
if(cfront[i]=='('){
lbox++;
}
else if(cfront[i]==')'){
if(lbox>0){
lbox--;
}
else{
status=0;
break;
}
}
}
if(status&&lbox==0){//匹配成功
result++;
pp=1;
getout(head,place);//断开place结点
free(curr);
reset(head,tail);//重置tail结点至尾结点
break;
}
char *cback=strcat(place->arr,curr->arr);
lbox=0;
status=1;
for(lli i=0;i<strlen(cback);i++){
if(cback[i]=='('){
lbox++;
}
else if(cback[i]==')'){
if(lbox>0){
lbox--;
}
else{
status=0;
break;
}
}
}
if(status&&lbox==0){//匹配成功
result++;
pp=1;
getout(head,place);//断开place结点
free(curr);
reset(head,tail);//重置tail结点至尾结点
break;
}
else{
place=place->next;
}
}
}
if(pp==0){//走完,没有匹配的,加到链表尾端
tail->next=curr;
curr->next=NULL;
tail=tail->next;
}
}
}
printf("%lld\n",result);
}
结果是这样的:
束手无策了……
【以下回答由 GPT 生成】
对于给定的n个括号序列,你想要找出最多能组成多少对合法括号序列的问题。在这个问题中,每个括号序列只能在一对中出现。你想要一个具体的解决方案,并展示相关的代码。
我可以提供一个解决方案来解决这个问题。首先,我们可以使用一个单链表来存储括号序列。在链表中,每个节点将表示一个括号序列,同时还存储左括号和右括号的数量。
以下是一个基本的解决方案的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char str[100];
int left;
int right;
struct Node* next;
} Node;
int main() {
int n;
scanf("%d", &n);
Node* head = NULL;
Node* current = NULL;
for (int i = 0; i < n; i++) {
char str[100];
scanf("%s", str);
int left = 0;
int right = 0;
for (int j = 0; j < strlen(str); j++) {
if (str[j] == '(') {
left++;
}
else if (str[j] == ')') {
if (left > 0) {
left--;
}
else {
right++;
}
}
}
if (head == NULL) {
head = (Node*)malloc(sizeof(Node));
current = head;
}
else {
current->next = (Node*)malloc(sizeof(Node));
current = current->next;
}
strcpy(current->str, str);
current->left = left;
current->right = right;
current->next = NULL;
}
int pairCount = 0;
current = head;
while (current != NULL) {
Node* temp = current->next;
if (current->left == 0 && current->right == 0) {
pairCount++;
free(current);
}
current = temp;
}
printf("最大的合法括号序列对数: %d", pairCount);
return 0;
}
这个解决方案使用一个头节点表示整个链表,并使用current指针来跟踪当前节点。在循环中,我们将输入的括号序列进行检查,计算左括号和右括号的数量。然后,我们创建一个新的节点,并将括号序列以及左右括号的数量存储在节点中。最后,我们遍历链表,计算符合要求的配对数并释放相应的节点。
希望这个解决方案对你有帮助!如果你有任何其他问题,请随时问我。