明天软考,但是今天还是手痒,在soj又切了道水题1663,看cauchy做了,故也来切掉。
题目意思是一串合法的表达式字符串,仅包括大写字母,+,-,(,),空格,tab字符,把多余的括号去掉。如:(A+(B+C)+(D-E)) ->A+B+C+D-E
或者((B))->B
思路:
1.堆栈操作字符串括号屁屁额
2. pos[top] = index ;//记录括号的位置
pre[top++] = ch ; //记录括号前的那个字符
num[i]//记录前i个字符有多少个大写字母。
vis[i]//标记第i个字符是否可以消掉
3.当且仅当pre[top-1]是+或者(时或者()之间字母数量<=1的时候该括号对要消掉。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
const int maxn = 1024 ;
char token , str[maxn] , ans[maxn] , pre[maxn] ;
int top , pos[maxn] , num[maxn] ;
bool vis[maxn] ;
void push(int index,char ch)
{
pos[top] = index ;
pre[top++] = ch ;
}
void pop()
{
top--;
}
inline void solve()
{
int i , k ;
char ch = '+' ;
memset(vis,0,sizeof(vis));
for ( i = 1 , top = num[0] = 0 ; str[i] ; i++)
{
num[i] = num[i-1] ;
if( str[i] == ' ' || str[i] == '\t' ) vis[i] = true ;
else if( str[i] == '(' )
{
push(i,ch);
ch = str[i] ;
}
else if( str[i] == ')' )
{
if( pre[top-1] == '(' || pre[top-1] == '+' || num[i] - num[pos[top-1]] <= 1 )
{
//去掉该括号
vis[pos[top-1]] = vis[i] = true ;
}
pop();
}
else if( str[i] >= 'A' && str[i] <= 'Z' )
{
num[i]++;
}
else if( str[i] == '+' )
{
ch = str[i] ;
}
else if( str[i] == '-' )
{
ch = str[i] ;
}
}
for( i = 1 , k = 0 ; str[i] ; i++)
if(!vis[i])
ans[k++] = str[i] ;
ans[k] = 0 ;
puts(ans);
}
int main()
{
int n ;
scanf("%d",&n); getchar();
while (n--)
{
gets(str+1);
solve();
}
}