数据结构算法c/c++版

1.一元多项式乘法

设计程序求两个一元多项式的和。

输入格式:

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数。数字间以空格分隔。

输出格式:

输出1行,以指数递降方式输出和多项式非零项的系数和指数(保证不超过整数的表示范围)。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。

输入样例:

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

输出样例:

5 20 -4 4 -5 2 9 1 -2 0

 

#include <stdio.h>
#include <stdlib.h>
typedef struct Node *List;
struct Node
{
	int base;
	int index;
	List next;
};
List Read();
List Add(List L1, List L2);
void PrintList(List L1);
void Attach(int b, int i, List*p);
List mul(List L1, List L2);

int main(void)
{
	List P1, P2, P3, P4;


	P1 = Read();
	P2 = Read();

	P3 = Add(P1, P2);


	PrintList(P3);
	return 0;

}


List Read()
{
	List p = (List)malloc(sizeof(struct Node));
	p->next = NULL;
	List r = p;
	int num;
	scanf("%d", &num);
	while (num--)
	{
		int base, index;
		scanf("%d %d", &base, &index);
		Attach(base, index, &r);
	}
	//r->next = NULL;
	List s = p;
	p = p->next;
	free(s);
	return p;
}

List Add(List L1, List L2)
{
	if (!L1 || !L2)
	{
		if (!L1)
		{
			return L2;
		}
		else
		{
			return L1;

		}
	}
	List p1 = L1, p2 = L2;
	List p = (List)malloc(sizeof(struct Node));
	p->next = NULL;
	List rare = p;

	while (p1&&p2)
	{
		if (p1->index == p2->index)
		{
			int base = p1->base + p2->base;
			if (base)
			{
				int index = p1->index;
				Attach(base, index, &rare);
			}
			p1 = p1->next;
			p2 = p2->next;
		}
		else if (p1->index > p2->index)
		{
			int index = p1->index;
			int base = p1->base;
			Attach(base, index, &rare);
			p1 = p1->next;
		}
		else
		{
			int index = p2->index;
			int base = p2->base;
			Attach(base, index, &rare);
			p2 = p2->next;
		}
	}

	rare->next = p1 ? p1 : p2;
	List r = p;
	p = p->next;
	free(r);
	return p;
}

void PrintList(List L1)
{
	if (!L1)
	{
		printf("0 0\n");
		return;
	}
	int flag = 1;
	List p = L1;
	while (p)
	{
		if (flag)
		{
			flag = 0;
		}
		else
		{
			printf(" ");
		}
		int base = p->base;
		int index = p->index;
		printf("%d %d", base, index);
		p = p->next;
	}
	printf("\n");
}

void Attach(int b, int i, List * p)
{
	List k = (List)malloc(sizeof(struct Node));
	k->base = b;
	k->index = i;
	k->next = NULL;

	(*p)->next = k;
	(*p) = (*p)->next;
}

2.最大子序列和

给定K个整数组成的序列{ N1​, N2​, ..., NK​ },“连续子列”被定义为{ Ni​, Ni+1​, ..., Nj​ },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据1:与样例等价,测试基本正确性;
  • 数据2:102个随机整数;
  • 数据3:103个随机整数;
  • 数据4:104个随机整数;
  • 数据5:105个随机整数;

输入格式:

输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2

输出样例:

20
#include <stdio.h>

#include <stdlib.h>

int main()
{

    int sum=0,maxsum=0,a,b,i,j,k,x,y,n,m;
    int shu[100005];
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&shu[i]);
        sum+=shu[i];
        if(sum>maxsum)
        {
            maxsum=sum;
        }
        else if(sum<0)sum=0;
    }
    printf("%d",maxsum);




    return 0;
}

3. 两个有序链表序列的合并

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。

输入格式:

输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。

输出格式:

在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL

输入样例:

1 3 5 -1
2 4 6 8 10 -1

输出样例:

1 2 3 4 5 6 8 10

 

#include <stdio.h>
#include <stdlib.h>
struct node
{
    int data;
    struct node *next;
};
int main()
{
    struct node *head1,*head2,*p,*q,*zong,*t1,*t2;

    int a,b;
    head1=(struct node *)malloc(sizeof(struct node));
    head1->next=NULL;

    t1=head1;

    head2=(struct node *)malloc(sizeof(struct node));
    head2->next=NULL;
    t2=head2;
    zong=(struct node *)malloc(sizeof(struct node));
    zong->next=NULL;
    while(~scanf("%d",&a))
    {

        if(a==-1)break;
        p=(struct node *)malloc(sizeof(struct node));
        p->data=a;
        p->next=NULL;
        t1->next=p;
        t1=p;

    }
    while(~scanf("%d",&b))
    {

        if(b==-1)break;
        p=(struct node *)malloc(sizeof(struct node));
        p->data=b;
        p->next=NULL;
        t2->next=p;
        t2=p;

    }
    p=head1->next;
    q=head2->next;
    t1=zong;
    while(p&&q)
    {
        if(p->data>=q->data)
        {
            t1->next=q;
            t1=q;
            q=q->next;

        }
        else
        {
            t1->next=p;
            t1=p;
            p=p->next;

        }

    }
    
    if(p==NULL)
    {
        t1->next=q;
        t1=q;
    }
    else if(q==NULL)
    {
        t1->next=p;
        t1=p;
    }
    if(head1->next==NULL&&head2->next==NULL)printf("NULL");
        else
    for(p=zong->next; p!=NULL; p=p->next)
    {
        if(p->next!=NULL)
        printf("%d ",p->data);
        else
            printf("%d\n",p->data);
    }






    return 0;
}

4.带头节点的双向循环链表操作、

本题目要求读入一系列整数,依次插入到双向循环链表的头部和尾部,然后顺序和逆序输出链表。

链表节点类型可以定义为

typedef int DataType;
typedef struct LinkedNode{
    DataType data;
    struct LinkedNode *prev;
    struct LinkedNode *next;
}LinkedNode;

链表类型可以定义为

typedef struct LinkedList{
  int length; /* 链表的长度 */
  LinkedNode head; /* 双向循环链表的头节点 */
}LinkedList;

初始化链表的函数可声明为

void init_list(LinkedList *list);

分配节点的函数可声明为

LinkedNode *alloc_node(DataType data);

头部插入的函数可声明为

void push_front(LinkedList *list, DataType data);

尾部插入的函数可声明为

void push_back(LinkedList *list, DataType data);

顺序遍历的函数可声明为

void traverse(LinkedList *list);

逆序遍历的函数可声明为

void traverse_back(LinkedList *list);

输入格式:

输入一行整数(空格分隔),以-1结束。

输出格式:

第一行输出链表顺序遍历的结果,第二行输出逆序遍历的结果。

输入样例:

在这里给出一组输入。例如:

1 2 3 4 5 6 -1

输出样例:

5 3 1 2 4 6
6 4 2 1 3 5

 

import java.util.Scanner;

// 链表节点
class Node{
	int val;
	Node pre;
	Node next;
	Node(int val, Node pre, Node next){
		this.val = val;
		this.pre = pre;
		this.next = next;
	}
}

public class Main {
	// 头指针作为前置节点
	public static Node head = new Node(0, null, null);
	public static Node tail = head;
	
	public static void main(String[] args) {
		
		Scanner cin = new Scanner(System.in);
		int n = 0, f = 0;
		while((n = cin.nextInt()) != -1) {
			if(f++ % 2 == 0) {
				addFirst(n);
			}else {
				addLast(n);
			}
		}
		
		showPre();
		System.out.println();
		showPost();
	}
	
	// 从头部插入
	public static void addFirst(int n) {
		Node old = head.next;
		Node t = new Node(n, head, old);
		head.next = t;
		if(head == tail) {
			tail = t;
		}else {
			old.pre = t;
		}
	}
	
	// 插入尾巴节点
	public static void addLast(int n) {
		Node t = new Node(n, tail, null);
		tail.next = t;
		tail = t;
	}
	
	// 前序遍历
	public static void showPre() {
		Node t = head.next;
		while(t != null) {
			if(t.next == null)
				System.out.print(t.val);
			else
				System.out.print(t.val + " ");
			t = t.next;
		}
	}
	
	// 倒序遍历
	public static void showPost() {
		Node t = tail;
		while(t != head) {
			if(t.pre == head)
				System.out.print(t.val);
			else
				System.out.print(t.val + " ");
			t = t.pre;
		}
	}
}

 5.进制转换

输入一个十进制的整数。将它转换为二进制数、八进制数和十六进制数。

输入格式:

输入一个不超过100的十进制整数。

输出格式:

在一行内输出对应的二进制数、八进制数和十六进制数,以空格隔开。

输入样例:

在这里给出一组输入。例如:

8

输出样例:

在这里给出相应的输出。例如:

1000 10 8

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a[50],b[50],c[50],n,m,i,j,k,d,r,x;
    scanf("%d",&n);
    if(n!=0)
    {

        x=m=d=n;
        i=0;
        while(n)
        {
            a[i]=n%2;
            n=n/2;
            if(a[i]<0)a[i]=-a[i];
            i++;
        }
        j=0;
        while(d)
        {
            b[j]=d%8;
            d/=8;
            if(b[j]<0)b[j]=-b[j];
            j++;
        }
        k=0;
        while(m)
        {
            c[k]=m%16;
            m/=16;
            if(c[k]<0)c[k]=-c[k];
            k++;
        }
        if(x<0)
        {
            printf("-");
        }
        for(r=i-1; r>=0; r--)
        {
            printf("%d",a[r]);
        }
        printf(" ");
        if(x<0)
        {
            printf("-");
        }
        for(r=j-1; r>=0; r--)
        {
            printf("%d",b[r]);
        }
        printf(" ");
        if(x<0)
        {
            printf("-");
        }
        for(r=k-1; r>=0; r--)
        {
            printf("%d",c[r]);
        }
    }
    else if(n==0)printf("0 0 0");
    return 0;
}

6.表达式转换

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:

输入在一行中给出不含空格的中缀表达式,可包含+-*/以及左右括号(),表达式不超过20个字符。

输出格式:

在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:

2+3*(7-4)+8/4

输出样例:

2 3 7 4 - * + 8 4 / +
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int IsNum( char c);
int IsZhengfu( char c);
int Compare( char a, char b);

int main()
{
    char str1[21];
    char str2[21];
    int len;
    int flag =0;
    int i,j;
    int space =0;

    scanf("%s",str1);
    len = strlen(str1);

    for( i=0; i<len; i++)
    {
        if(IsNum(str1[i]))
        {

            if( space )
            {
                printf(" ");
                space = 0;
            }
            printf("%c",str1[i]);
        }
        else if( IsZhengfu(str1[i]) && (i? str1[i-1]=='(':1))
        {

            if( str1[i]=='-')
            {
                if(space)
                {
                    printf(" ");
                    space = 0;
                }
                printf("%c",str1[i]);
            }
        }
        else
        {
            if( flag)
            {
                if( str1[i]==')')
                {

                    while( flag--)
                    {
                        if(str2[flag]=='(') break;
                        printf(" %c",str2[flag]);
                    }
                }
                else
                {
                    while( flag )
                    {

                        if( Compare( str2[flag-1],str1[i]))
                        {
                            printf(" %c",str2[--flag]);
                        }
                        else break;
                    }
                    str2[flag++] = str1[i];
                }
            }
            else str2[flag++] = str1[i];
            for ( j=0; j<flag; j++)
            {
                if( str2[j]!='(')
                {

                    space = 1;
                    break;
                }
            }
        }
    }
    while (flag)
    {
        printf(" %c",str2[--flag]);
    }

    return 0;
}

int IsNum( char c)
{

    return ( c >='0'&&c<='9')||c=='.';
}

int IsZhengfu( char c)
{
    return c=='+' || c=='-';
}

int Compare( char a, char b)
{

    if( b==')') return 1;
    if( b=='(' || a=='(') return 0;

    switch(b)
    {
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
        switch(a)
        {
        case '+':
        case '-':
            return 0;
        case '*':
        case '/':
            return 1;
        }

    }
}

 7.冬奥会接驳车

艾灵是冬奥会的一名运动员,今天她准备从奥运村前往比赛场馆进行比赛,本届冬奥会科技感十足,奥组委配备了无人驾驶的接驳车。假定你是奥组委的软件工程师,请你为无人接驳车编写路径规划程序,使其载着艾灵以最短的时间到达目的地。

接驳车的运行范围可以被建模为一张由n行m列单元格组成的地图。有的单元格是空地,可以走;有的单元格处是障碍物,不能走。假定接驳车只可以朝上、下、左、右四个方向行驶,不能斜着走。每行驶过一个位置(单元格)需要1分钟。给定地图以及艾灵的起点和终点,请输出接驳车从起点行驶到终点所需的最短时间。

输入格式:

输入包含多组数据。每组数据第一行是两个整数n和m (1≤ m, n ≤100),表示地图的长和宽;接下来是n行,每行m个数字,表示整个地图。空地格子用0表示,障碍物用1表示,艾灵所在起点用3表示,目的地用4表示。

输出格式:

对于每组数据,如果接驳车能够到达目的地,输出一个整数,表示艾灵从起点到目的地所需的最短时间,如果不能到达目的地,输出“unreachable”。

输入样例:

5 5
1 0 1 1 1
1 0 4 1 0
1 0 0 1 0
0 0 0 1 0
1 0 3 0 1
5 5
3 0 1 1 1
1 0 1 1 0
1 0 1 1 0
0 0 0 1 0
1 0 1 0 4

输出样例:

3
unreachable

 

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, pair<int, int>> PII;
const int N = 110;

int n, m, ans = -1;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
char a[N][N];
bool st[N][N];

int bfs(int x, int y)
{
	queue<PII> q;
	q.push({0, {x, y}});
	st[x][y] = true;
	while(q.size())
	{
		PII t = q.front();
		q.pop();
		
		int xx = t.second.first, yy = t.second.second;
		
		if(a[xx][yy] == '4') return t.first;
 		
		for(int i = 0; i < 4; i ++ )
		{
			int nx = xx + dx[i], ny = yy + dy[i];
			if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
			if(st[nx][ny]) continue;
			if(a[nx][ny] == '1') continue;
			
			q.push({t.first + 1, {nx, ny}});
			st[nx][ny] = true;
		}
	}
	return -1;
}

int main()
{
	int x, y;
	cin >> n >> m;
	for(int i = 0; i < n; i ++ )
	{
		for(int j = 0; j < m; j ++ )
		{
			cin >> a[i][j];
			if(a[i][j] == '3')
			{
				x = i, y = j;
			}
		}
	}
	
	ans = bfs(x, y);
	
	if(ans == -1) cout << "unreachable";
	else cout << ans ;
	
}

8.行编辑器

一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区。
由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的。较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时可以及时更正。例如,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符"#",以表示前一个字符无效;
如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符"@",以表示当前行中的字符均无效。
如果已经在行首继续输入'#'符号无效。

输入格式:

输入一个多行的字符序列。但行字符总数(包含退格符和退行符)不大于250。

输出格式:

按照上述说明得到的输出。

输入样例1:

在这里给出一组输入。例如:

whli##ilr#e(s#*s)

输出样例1:

在这里给出相应的输出。例如:

while(*s)

输入样例2:

在这里给出一组输入。例如:

outcha@putchar(*s=#++);

输出样例2:

在这里给出相应的输出。例如:

putchar(*s++);
#include <stdio.h>
#include <string.h>

int main()
{
    int top, len;
    char a[300], b[300];
    while (gets(a))
    {
        top = 0;
        for (int i = 0; a[i]; i++)
        {
            if (a[i] == '#')
            {
                if (top != 0)
                    top--;
            }
            else if (a[i] == '@')
            {
                if (top != 0)
                {
                    while (top != 0)
                        top--;
                }
            }
            else
                b[top++] = a[i];
        }
        for (int i = 0; i < top; i++)
        {
            if (i == top - 1)
                printf("%c\n", b[i]);
            else
                printf("%c", b[i]);
        }
    }
    return 0;
}

 9.朋友圈

某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。

输入格式:

输入的第一行包含两个正整数N(≤30000)和M(≤1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:

第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi

输出格式:

输出给出一个整数,表示在最大朋友圈中有多少人。

输入样例:

7 4
3 1 2 3
2 1 4
3 5 6 7
1 6

输出样例:

4
#include <stdio.h>
#include <stdlib.h>
int pre[30005];
int root[30005];
int find(int x){
    if(pre[x]!=x){
        pre[x] = find(pre[x]);
    }
    return pre[x];
}
void join(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx!=fy){
        pre[fx] = fy;
    }
}
int main()
{
    int m,n;
    scanf("%d %d",&m,&n);
    for(int i=1;i<=m;i++){
        pre[i] = i;
    }
    while(n--){
        int k,arr[30005];
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            scanf("%d",&arr[i]);
        }
        for(int i=2;i<=k;i++){     
            join(arr[1],arr[i]);
        }
    }
    int max = 0;
    for(int i=1;i<=m;i++){
        int t = find(i);
        root[t]++;
        if(root[t]>max)max = root[t];
    }
    printf("%d",max);
    return 0;
}

 10.部落

在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。

输入格式:

输入在第一行给出一个正整数N(≤104),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:

K P[1] P[2] ⋯ P[K]

其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过104。

之后一行给出一个非负整数Q(≤104),是查询次数。随后Q行,每行给出一对被查询的人的编号。

输出格式:

首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y,否则输出N

输入样例:

4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7

输出样例:

10 2
Y
N
#include <bits/stdc++.h>

using namespace std;
int pre[10005];
int arr[10005];
int sum=0,num=0;
int finde(int x)
{
    if(pre[x]==x)
        return x;
    return pre[x]=finde(pre[x]);
}
void bcj(int x,int y)
{
    x=finde(x);
    y=finde(y);
    if(x==y)
        return;
    else pre[y]=x;
}
int main()
{
    int i,j,k,n,m,c,d;
    int t=0;
    cin>>n;
    for(j=1; j<=10005; j++)
    {
        pre[j]=j;
    }
    for(i=0; i<n; i++)
    {
        cin>>m;
        for(j=0; j<m; j++)
        {
            cin>>arr[j];
            if(sum<arr[j])
                sum=arr[j];
        }
        for(j=1; j<m; j++)
        {
            bcj(arr[0],arr[j]);
        }
    }
    for(i=1;i<=sum;i++)
    {
        if(pre[i]==i)num++;
    }
    cout<<sum<<" "<<num<<endl;
    cin>>k;
    for(i=0; i<k; i++)
    {
        cin>>c>>d;
        if(finde(c)==finde(d))
            cout<<"Y"<<endl;
        else
            cout<<"N"<<endl;
    }
    return 0;
}

 11.串的模式匹配

给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。

本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据0:小规模字符串,测试基本正确性;
  • 数据1:随机数据,String 长度为 105,Pattern 长度为 10;
  • 数据2:随机数据,String 长度为 105,Pattern 长度为 102;
  • 数据3:随机数据,String 长度为 105,Pattern 长度为 103;
  • 数据4:随机数据,String 长度为 105,Pattern 长度为 104;
  • 数据5:String 长度为 106,Pattern 长度为 105;测试尾字符不匹配的情形;
  • 数据6:String 长度为 106,Pattern 长度为 105;测试首字符不匹配的情形。

输入格式:

输入第一行给出 String,为由英文字母组成的、长度不超过 106 的字符串。第二行给出一个正整数 N(≤10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 105 的字符串。每个字符串都非空,以回车结束。

输出格式:

对每个 Pattern,按照题面要求输出匹配结果。

输入样例:

abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz

输出样例:

abcabcacabxy
Not Found
Not Found

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char zhu[1000005],fu[1000005];
int nextt[1000005];
void nextx(int f)
{
    int i=2;
    nextt[1]=0;
    int j=0;
    while(i<=f)
    {

        while(j!=0&&fu[j+1]!=fu[i])
        {
            j=nextt[j];
        }
        if(fu[j+1]==fu[i])
        {
            j++;
        }
        nextt[i]=j;
        i++;
    }



}
int kmp(int l,int f)
{
    int i=1,j=0;
    while(i<=l)
    {
        while(j>0&&fu[j+1]!=zhu[i])
        {

            j=nextt[j];
        }
        if(fu[j+1]==zhu[i])j++;
        if(j==f)
        {

            return i-j+1;
        }
        i++;
    }
    return 0;

}
int main()
{
    gets(zhu+1);
    int l=strlen(zhu+1);
    int n,m,a,v,b,c,i,j,k,f;
    scanf("%d",&n);
    getchar();
    for(i=0; i<n; i++)
    {

        gets(fu+1);
        f=strlen(fu+1);
        nextx(f);
        m=kmp(l,f);
        if(m==0)printf("Not Found\n");
        else
        {
            for(j=m; j<=l; j++)
            {
                printf("%c",zhu[j]);
            }
            printf("\n");
        }

    }
    return 0;
}

12.字符串模式匹配

给定主串s和模式串p,编写程序输出p在s中出现的首位置,若p不在s中则输出-1。字符串下标从0开始。

输入格式:

输入为2行,第1行主串s,第2行为模式串p。主串和模式串长度大于4,不超过105。

输出格式:

输出为2行,第1行为3个整数,表示分别在模式串p的m/4、2m/4、3m/4处匹配失败后,模式串下一次匹配的位置,每个整数后一个空格,m表示模式串p的长度;第2行为一个整数,表示p在s中出现的首位置,若p不在s中则输出-1。

输入样例:

qwerababcabcabcabcdaabcabhlk
abcabcabcabc

输出样例:

0 3 6 
6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char zhu[1000005],fu[1000005];
int nextt[1000005];
void nextx(int f)
{
    int i=2;
    nextt[1]=0;
    int j=0;
    while(i<=f)
    {

        while(j!=0&&fu[j+1]!=fu[i])
        {
            j=nextt[j];
        }
        if(fu[j+1]==fu[i])
        {
            j++;
        }
        nextt[i]=j;
        i++;
    }



}
int kmp(int l,int f)
{
    int i=1,j=0;
    while(i<=l)
    {
        while(j>0&&fu[j+1]!=zhu[i])
        {

            j=nextt[j];
        }
        if(fu[j+1]==zhu[i])j++;
        if(j==f)
        {

            return i-j+1;
        }
        i++;
    }
    return 0;

}
int main()
{
    gets(zhu+1);
    int l=strlen(zhu+1);
    int n,m,a,v,b,c,i,j,k,f;
    gets(fu+1);
        f=strlen(fu+1);
    nextx(f);
    m=kmp(l,f);
    for(i=1;i<=f;i++)
    {

        printf("%d ",nextt[i]-1);
        
    }
    printf("\n");
    printf("%d",m-1);
    return 0;
}

13.三元组顺序表表示的稀疏矩阵转置Ⅱ

三元组顺序表表示的稀疏矩阵转置Ⅱ。设a和b为三元组顺序表变量,分别表示矩阵M和T。要求按照a中三元组的次序进行转置,并将转置后的三元组置入b中恰当的位置。

输入格式:

输入第1行为矩阵行数m、列数n及非零元素个数t。
按行优先顺序依次输入t行,每行3个数,分别表示非零元素的行标、列标和值。

输出格式:

按置入b中的顺序输出置入的位置下标,转置后的三元组行标、列标和值,数据之间用空格分隔,共t行。

输入样例1:

3 4 3
0 1 -5
1 0 1
2 2 2

输出样例1:

1 1 0 -5
0 0 1 1
2 2 2 2

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct pe
{
    int i,j;
    int da;
} que;
typedef struct r
{
    que zu[1001];
    int hang,lie,fei;

} qqe;
int main()
{

    int n,m,a,v,b,c,i,j,k,f;
    qqe ju,zz;
    scanf("%d %d %d",&ju.hang,&ju.lie,&ju.fei);
    zz.hang=ju.lie;
    zz.lie=ju.hang;
    zz.fei=ju.fei;
    for(i=0; i<ju.fei; i++)
    {
        scanf("%d %d %d",&ju.zu[i].i,&ju.zu[i].j,&ju.zu[i].da);
    }
    if(ju.fei)
    {
        int count=0;
        for(k=0; k<ju.lie; k++)
        {
            for(f=0; f<ju.fei; f++)
            {
                if(ju.zu[f].j==k)
                {
                    zz.zu[count].i=ju.zu[f].j;
                    zz.zu[count].j=ju.zu[f].i;
                    zz.zu[count].da=ju.zu[f].da;
                    count++;
                }
            }
        }
        for(k=0; k<ju.hang; k++)
        {
            for(f=0; f<ju.fei; f++)
            {
                if(zz.zu[f].j==k)
                {
                    printf("%d %d %d %d\n",f,zz.zu[f].i,zz.zu[f].j,zz.zu[f].da);
                }
            }
        }
    }

    return 0;
}

 14.列出连通集

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1​ v2​ ... vk​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

 

#include <bits/stdc++.h>
using namespace std;
#define MAX_MM 999999
int tu[15][15],vis[15];
int n,m;
void DFS(int f)
{
    cout<<" "<<f;
int j;
    vis[f]=1;
    for(j=0;j<n;j++)
    if(vis[j]!=1&&tu[f][j]==1)
    {
        DFS(j);

    }
}
void BFS(int f)
{
    deque<int> s;
    s.push_back(f);
    vis[f]=1;
    while(s.size()!=0)
    {
        int t=s.front();
        s.pop_front();;
        cout<<" "<<t;
        for(int i=0;i<n;i++)
        {
            if(vis[i]!=1&&tu[t][i]==1)
            {
                s.push_back(i);
                vis[i]=1;
            }
        }
    }
}
int main()
{
    int i,j,x,y;
    cin>>n>>m;
    memset(tu,MAX_MM,sizeof tu);
    for(i=0;i<m;i++)
    {
        cin>>x>>y;
        tu[x][y]=tu[y][x]=1;
    }
    for(i=0;i<n;i++)
    {
        if(vis[i]!=1)
        {
            cout<<"{";
            DFS(i);
            cout<<" }"<<endl;
        }
    }
    memset(vis,0,sizeof vis);
    for(i=0;i<n;i++)
    {
        if(vis[i]!=1)
        {
            cout<<"{";
            BFS(i);
            cout<<" }"<<endl;
        }
    }
    return 0;
}

15.哈利·波特的考试

哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。

现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。

输入格式:

输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。

输出格式:

输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。

输入样例:

6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80

输出样例:

4 70
#include <bits/stdc++.h>
using namespace std;
int tu[105][105];
int n,m;
int dist[105][105];
int finde(int i)
{
    int maxx=0,j;
    for(j=1; j<=n; j++)
    {
        if(dist[i][j]>maxx)maxx=dist[i][j];
    }
    return maxx;
}
int main()
{
    int a,b,c;
    int i,j,k;
    cin>>n>>m;
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=n; j++)
        {
            if(i==j)
            {
                tu[i][j]=0;
            }
            else
            {
                tu[i][j]=9999;
            }

        }
    }
    for(i=0; i<m; i++)
    {
        cin>>a>>b>>c;
        tu[a][b]=c;
        tu[b][a]=c;
    }
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=n; j++)
        {
            dist[i][j]=tu[i][j];
        }
    }
    for(k=1; k<=n; k++)
    {
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=n; j++)
            {
                if(dist[i][j]>dist[i][k]+dist[k][j])
                {
                    dist[i][j]=dist[i][k]+dist[k][j];
                }
            }
        }
    }
    int am=0;
    int minn=9999;
    for(int i=1; i<=n; i++)
    {
        int sm=finde(i);
        if(sm==9999)
        {
        cout<<0<<endl;
           return 0;
        }
        else
        {
            if(minn>sm)
            {
                minn=sm;
                am=i;
            }
        }
    }
cout<<am<<" "<<minn;
    return 0;
}




 15.旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

输出格式:

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

3 40
#include <bits/stdc++.h>
using namespace std;
#define MAX_MM 999999
int tu[505][505],vis[505],ut[505][505],dis[505],price[505];
int n,m;

int main()
{
    int i,j,x,y,z,k,s,d,t;
    cin>>n>>m>>s>>d;
    memset(tu,MAX_MM,sizeof tu);
    memset(ut,MAX_MM,sizeof ut);
    memset(dis,MAX_MM,sizeof dis);
    memset(price,MAX_MM,sizeof price);
    for(i=0; i<m; i++)
    {
        cin>>x>>y>>z>>k;
        tu[x][y]=tu[y][x]=z;
        ut[x][y]=ut[y][x]=k;
    }
    dis[s]=price[s]=0;
    vis[s]=1;
    for(i=0; i<n; i++)
    {
        t=s;
        int minn=MAX_MM;
        for(j=0; j<n; j++)
        {

            if(vis[j]!=1&&dis[j]<minn)
            {
                minn=dis[j];
                t=j;
            }
        }
        vis[t]=1;
        for(j=0; j<n; j++)
        {
            if(dis[j]>tu[t][j]+dis[t])
            {
                dis[j]=tu[t][j]+dis[t];
                price[j]=ut[t][j]+price[t];
            }
            else if(dis[j]==tu[t][j]+dis[t])
            {
                price[j]=min(price[j],price[t]+ut[t][j]);
            }
        }

    }
cout<<dis[d]<<" "<<price[d];
    return 0;
}



 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值