PTA数据结构题

7-27表达式求值

给定一个中缀表达式,请编写程序计算该表达式的值。表达式包含+、-、*、\、(、),所有运算均为二元运算,操作数均为正整数,但可能不止一位,不超过5位。运算结果为整数,值域为[−231,231)。除法运算结果若为小数则进行截尾取整。若除法运算中除数为0,则输出ILLEGAL。

输入格式:

输入为一个字符串,表示中缀表达式。

输出格式:

输出为一个整数,为表达式的值;或者为一个字符串ILLEGAL。

输入样例1:

5+(10*2)-6

输出样例1:

19

输入样例2:

8*(999+1)

输出样例2:

8000

输入样例3:

1+5/(1-1)

输出样例3:

ILLEGAL

#include<stdio.h>
#include<string.h>


int in(char ch)
{
	if (ch <= '9' && ch >= '0')
		return 1;
	return 0;
}

int A(int a, char c, int b, int* flag)
{
	if (c == '*')
		return a * b;
	else if (c == '/') {
		if (b == 0)
			*flag = 1;
		else
			return a / b;
	}
	else if (c == '-')
		return a - b;
	else if (c == '+')
		return a + b;
}

int B(char a, char b)
{
	int x = 0;
	int y = 0;
	if (a == '+' || a == '-')
		x = 1;
	else if (a == '*' || a == '/')
		x = 2;
	else if (a == '(')
		x = 3;
	if (b == '+' || b == '-')
		y = 1;
	else if (b == '*' || b == '/')
		y = 2;
	else if (b == '(')
		y = 3;
	if (x > y)return 1;
	return 0;
}
int main()
{

	char s[1000];
	int num[1000];
	char ch[1000];
	int flag = 0;
	fgets(s, 990, stdin);
	int a = 0, b = 0;
	for (int i = 0; i < 1000; i++)
	{
		num[i] = 0;
		ch[i] = '0';
	}

	int i = 0;
	while (i < strlen(s))
	{
		if (in(s[i]))//如果是数字则入num
		{
			while (in(s[i]))
				num[a] = num[a] * 10 + s[i++] - '0';//多位数的情况
			a++;
			continue;
		}
		else//不是数字
		{
			if (s[i] == '(') //遇到左括号直接入ch【】
				ch[b++] = s[i];
			else if (s[i] == ')')//遇到右括号计算
			{
				while (ch[b - 1] != '(')
				{
					num[a - 2] = A(num[a - 2], ch[b - 1], num[a - 1], &flag);
					num[a - 1] = 0;
					b--;//改变符号栈栈顶
					a--;//改变数字栈栈顶
				}
				b--;
			}
			else {//遇到运算符
				if (b == 0) //符号栈为空,直接入
					ch[b++] = s[i];
				else if (B(s[i], ch[b - 1]))//判断当前符号与符号栈栈顶元素的优先级,如果当前元素优先级大直接入
					ch[b++] = s[i];
				else //栈顶元素优先级小,进行计算
				{
					while (!B(s[i], ch[b - 1])) {
						if (ch[b - 1] == '(')//多重括号的情况
							break;
						num[a - 2] = A(num[a - 2], ch[b - 1], num[a - 1], &flag);
						num[a - 1] = 0;
						b--;
						a--;
						if (b == 0)break;
					}
					ch[b++] = s[i];//计算完后将此符号入ch【】
				}
			}
		}
		i++;
	}
	while (a != 1 && b > 0)//数字栈数组中剩余两位,符号剩余一位
	{
		num[a - 2] = A(num[a - 2], ch[b - 1], num[a - 1], &flag);
		a--;
		b--;

	}
	if (flag == 1)
		printf("ILLEGAL");
	else
		printf("%d", num[0]);
}

 

7-28 贝蒂买桔子

贝蒂去超市买桔子,超市有n个桔子,每个桔子都有唯一的英文字母标号,贝蒂打算从所有桔子中挑选出若干个桔子买(也可能一个都不买),请编写程序帮助贝蒂求出所有可能的挑法。每种挑法按字典序给出各桔子的标号。

字典序,即字符串在字典中的顺序。对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小,例如abc比abd小。

输入格式:

输入为一个正整数n,表示超市里的桔子个数,n不超过15。桔子的标号为a, b, c, d…。若n=1,桔子为a;若n=3,桔子为a, b, c;若n=4,桔子为a, b, c, d;以此类推。

输出格式:

输出为若干行字符串,每行表示贝蒂的一种挑法。每种挑法用{}包含,每个桔子的标号用西文逗号间隔,例如{a,b,c},标号须按字典序排列。“什么也不买”对应的挑法最先输出,为{},中间无空格。

输入样例:

3

输出样例:

{}
{a}
{a,b}
{a,b,c}
{a,c}
{b}
{b,c}
{c}

 答

#include <stdio.h>


// n不超过15
int ans[20];
int used[20]; // 记录每个数是否被用
int n;

void dfs(int u){
    
    printf("{");
    if(1!=u) printf("%c", 'a'-1+ans[1]);
    for(int i=2; i<u; i++)
        printf(",%c", 'a'-1+ans[i]);
    printf("}\n");
    
    
    for(int i=u; i<=n; i++)
        if(used[i]) continue;
        else if(i>ans[u-1]){
            ans[u]=i;
            used[i]=1;
            dfs(u+1);
            used[i]=0;
        }
}

int main(){
    scanf("%d",&n);
    
    dfs(1);
    
    return 0;
}

7-29 好中缀

我们称一个字符串S的子串T为好中缀,如果T是去除S中满足如下条件的两个子串p和q后剩余的字符串。

(1)p是S的前缀,q是S的后缀;

(2)p=q;

(3)p和q是满足条件(1)(2)的所有子串中的第二长者。

注意一个字符串不能称为自己的前缀或后缀。好中缀至少为空串,其长度大于等于0,不能为负数。

输入格式:

输入为一个字符串S,包含不超过100000个字母。

输出格式:

输出为一个整数,表示好中缀的长度。

输入样例1:

abcabcxxxabcabc

输出样例1:

9

输入样例2:

xacbacba

输出样例2:

8

输入样例3:

aaa

输出样例3:

1

答 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10000010
int next[N],ans[N];
char s[N];
int ls;

void Next(){
    int j=0;
    for(int i=2;i<=ls;i++){
        while(j>0&&s[j+1]!=s[i]){
            j=next[j];
        }
        if(s[j+1]==s[i]){
            j++;
        }
        next[i]=j;
    }
}

int main()
{
    scanf("%s",s+1);

    ls=strlen(s+1);

    Next();
    int t=ls;
   int c=0;
   while(t>0){
    t=next[t];  // 递推求得 相同前后缀 的子串 的长度
    ans[++c]=t; // 并逐个存到数组中,数组下标从1到cnt
   }
   if(c==0){    // 说明没有相同前后缀,输出原长度
    printf("%d\n",ls);
   }
   else{
    int n=ls-2*ans[2];
    if(n<0) n=0;  // 比如s = "aaaa"
    printf("%d\n",n);
   }
    return 0;
}

 

7-30 破译报文

小明接到一个破解报文的任务:该报文是一串文本,破解出的密文应是在报文串中出现次数大于1的所有子串中的最长者。规定报文本身不能称为自己的子串。请编写效率尽可能高的程序帮小明完成这个棘手的任务。

输入格式:

输入为一个字符串,表示报文,包含不超过10000个字母。

输出格式:

输出为一个整数,表示破解出的密文串的长度。

输入样例1:

xabceabcf

输出样例1:

3

输入样例2:

xyabcabcayx

输出样例2:

4

 答

#include <iostream>
#include <cstring>
using namespace std;

const int N=1e4+10;

string s;
int n;
int a[N];

void quick_sort(int q[], int l, int r){
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    string sx=s.substr(x, n-x);
    // s.substr(q[i], n-q[i])
    while (i < j){
        do i ++ ; while (s.substr(q[i], n-q[i]) < sx);
        do j -- ; while (s.substr(q[j], n-q[j]) > sx);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

int main(){
    cin>>s;
    int n=s.size();
    for(int i=0; i<n; i++) a[i]=i; // 截取
    
    quick_sort(a, 1, n-1);
    
    //for(int i=0; i<n; i++)
    //    cout<<s.substr(i, n-i)<<endl;
    
    int ans=0;
    for(int i=0; i<n; i++){
        string x=s.substr(a[i], n-a[i]);
        string y=s.substr(a[i+1], n-a[i+1]);
        int res=0;
        for(int j=0; j<x.size() && j<y.size(); j++)
            if(x[j]==y[j]) res++;
            else break;
        ans=max(ans, res);
    }
    cout<<ans<<endl;
    return 0;
}

 在此还是感谢戴老大的帮助~~~~~~~~你是我的神!!!!!!!!!!

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值