字符串和多维数组的算法问题

1.字符串匹配(BF算法)

【问题描述】给定两个字符串S和T,在主串中寻找字串T的过程称为模式匹配,T称为模式。如果匹配成功,返回T在S中的位置;如果匹配失败,返回0。
【输入形式】两行,第一行是主串S,第二行是模式串T

【输出形式】模式串T第一次出现在主串S中的位置。

【样例输入】abcabcacb

                    abcac
【样例输出】4
【样例说明】注意返回的是模式串在主串的位置,区别存储时的角标。
【评分标准】注意读入字符时,有可能中间含有空格字符。所以可以用getline读取字符串。

#include <iostream>
#include <string>
using namespace std;
int bs(string s, string t);
int main()
{
	string s;
	string t;
	getline(cin, s);
	getline(cin, t);

	cout << bs(s, t);
}
int bs(string s, string t) {
	int i = 0, j = 0;
	while ((s[i] !='\0') && (t[j] !='\0')) {
		if (s[i] == t[j]) {
			i++;
			j++;
		}
		else {
			i = i - j + 1;
			j = 0;
			/*
			a b c d a b d e
			a b d
			主1、主2与模式1、模式2均匹配,主3与模式3不匹配
			所有主串从第二个(b)开始和字串第一个比较
			*/
		}
	}
	if (t[j] == '\0') return i - j + 1;
	else return 0;
}

2.从pos位置开始求子串

【问题描述】

          从串str中的pos位置起,求出与substr串匹配的子串的位置,如果str为空串,或者串中不包含与substr匹配的子串,则返回0做标记。

【输入形式】三行,第一行是主串str,第二行是模式串substr;第三行是pos的数值;

【输出形式】模式串substr第一次出现在主串str中从pos位置开始出现的位置(失败时返回0)。

【样例输入】ababcacb

                      ab

                    2

【样例输出】

     3

#include <iostream>
#include <string>
using namespace std;
int bs(string s, string t,int n);
int main()
{
	string s;
	string t;
	int n;
	getline(cin, s);
	getline(cin, t);
	cout << bs(s, t, n);
}
int bs(string s, string t,int n) {
	int i = 0, j = 0;
	while ((s[i] != '\0') && (t[j] != '\0')) {
		if (s[i] == t[j]) {
			i++;
			j++;
		}
		else {
			i = i-j+1;
			j = 0;
		}
	}
	if (t[j] == '\0') return i-j + 1;
	else return 0;
}

3.字串出现次数的统计

【问题描述】编写一个函数,计算一个子串在一个主串中出现的次数,如果该字串不出现,则返回0。本题不需要考虑子串重叠,如:主串为aaaa,子串为aaa,考虑子串重叠结果为2,不考虑子串重叠结果为1。

【输入形式】主串S和子串T。
【输出形式】子串在主串中出现的次数,如果没有出现,则输出0。
【样例输入】

                    ABCDFDEG

                    CD

【样例输出】1
【样例说明】子串CD在主串中出现了一次

#include <iostream>
#include <string>
using namespace std;
int bs(string s, string t) {
	int i = 0, j = 0;
	int count = 0;
	while (s[i] != '\0') {//条件改为主串不为零,(一直往下匹配直至主串到头)
		if (s[i] == t[j]) {
			i++;
			j++;
		}
		else {
			i = i - j + 1;
			j = 0;
		}
		if (t[j] == '\0') {
			count++;
			//i++;无需此条,模式到头后,主串并没有到头,会继续执行循环
			//若加上i+,会出现跳跃
			j = 0;
		}
	}
	if (s[i] == '\0') return count;
	else return 0;
}
int main()
{
	string s;
	string t;
	int n;
	getline(cin, s);
	getline(cin, t);
	cout << bs(s, t);
}

4.公共子序列

【问题描述】模式匹配时严格的匹配,即强调模式在主串中的连续性,例如,模式“bc”是主串"abcd"的子串,而"ac"就不是主串“abcd”的子串。但在实际应用中,有时不需要模式的连续性,例如,模式“曲师大”与主串“曲阜师范大学”是非连续匹配,称模式“曲师大”是主串“曲阜师范大学”的子序列。要求设计算法,判断给定的模式是否为两个主串的公共子序列。如果是公共子序列,则输出“YES”;否则输出“NO”。

【输入形式】第一行是主串S1、第二行是主串S2、第三行是子串T。

【输出形式】子串T是否是主串S1和S2的公共子序列。如果是则输出“YES”,否则输出“NO”。

【样例输入】

  abcdef

  cdef

  cd

【样例输出】YES

#include <iostream>
#include <string>
using namespace std;
int mat(string s, string t);
int main()
{
	string s;
	string t;
	string m;
	getline(cin, s);
	getline(cin, t);
	getline(cin, m);
	int a = mat(s, m);//比较3是否是1的子序列
	int b = mat(t, m);//比较3是否是2的子序列
	if (a && b) cout << "YES";
	else cout << "NO";

}
int mat(string s, string t) {//判断是否是子串的函数
	int i = 0, j = 0;
	while ((s[i] != '\0') && (t[j] != '\0')) {
		if (s[i] == t[j]) {
			i++;
			j++;
		}
		else {
			i++;//i继续往前走,只需要主串中含有模式中的字符就可以,无需每次回溯
			/*
			a b c d a b d
			
			a b d
			第三个不符合,模式第三个继续和主串第4个比,依次往下,直至找到
			*/
		}
	}
	if (t[j] == '\0') return 1;//返回值为1
	else return 0;
}

5.移动非零元素

【问题描述】设数组A[0,……,n-1]的n个元素中有多个零元素,设计一个算法,将A中所有的非零元素依次移动到A数组的前端。最后打印数组A,保证非零元素都在前端输出。

【输入形式】数组元素的个数n以及数据元素(中间用空格隔开)。

【输出形式】移动非零元素后的数组。

【样例输入】

                         8

                         1 0 0 3 0 1 0 2

【样例输出】1 3 1 2 0 0 0 0

【提示说明】从左到右扫描整个数组,当发现非零元素时,使其尽可能与靠左边的零元素进行交换。

#include <iostream>
using namespace std;
int change(int *a,int *b) {
	int t;
			t = *a;
			*a = *b;
			*b = t;

			return *a;
}
int main() {
	int n;
	cin >> n;
	int arr[100];
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
	}
	for (int i = 0; i < n; i++) {//比较n次,类似冒泡
		for (int j = 0; j < n - 1; j++) {//左边与右边交换位置
			if (arr[j] == 0) {
				change(&arr[i], &arr[j]);
			}
		}
	}
	for (int i = 0; i < n; i++) {
		cout << arr[i] << " ";
	}
}

6.字符串匹配(KMP算法)

【问题描述】给定两个字符串S和T,在主串中寻找字串T的过程称为模式匹配,T称为模式。如果匹配成功,返回T在S中的位置;如果匹配失败,返回0。记主串S的长度为n,模式串T的长度为m,则传统BF算法最好情况下的时间复杂度为O(n+m),最差情况下的时间复杂度为O(n*m),时间复杂度太高,而且主要是由于主串回溯造成的,为了减少主串无意义的回溯,所以提出了KMP算法,在KMP算法中需要用到next数组,因而先根据模式串求解出next数组。

S7.png

【输入形式】两行,第一行是主串S,第二行是模式串T

【输出形式】第一行表示模式串T第一次出现在主串S中的位置(失败时返回0)。第二行是KMP算法中next数组的内容(中间用空格隔开)。

【样例输入】

                    abcabcacb

                    abcac

【样例输出】

                   4

                   -1 0 0 0 1

【样例说明】1、注意返回的是模式串在主串的位置,区别存储时的角标。

#include <iostream>
#include <string>
using namespace std; 
int KMP(string S, string T,int next[]) {
	int i = 0;
	int j = 0;
	while ((S[i] != '\0') && (T[j] != '\0')) {
		if (S[i] == T[j]) {
			i++;
			j++;
		}
		else {
			j = next[j];
		}
		if (j == -1) {
			i++;
			j++;
		}
	}
	if (T[j] == '\0') {
		return i - j + 1;
	}
	else return 0;
}
int acount(string t) {
	int n = 0;
	while (t[n]!='\0') {
		n++;
	}
	return n;
}
void getNext(string T, int length, int next[])//计算next函数值
{
	int m = 0, k = -1;
	next[0] = -1;
	while (m < length)
	{
		if (k == -1 || T[m] == T[k])
			next[++m] = ++k;
		else
			k = next[k];
	}
}
int main()
{
	string s;
	string t;
	getline(cin, s);
	getline(cin, t);
	int n = acount(t);
	int next[100];
	getNext(t, n, next);
	cout << KMP(s, t, next) << endl;
	for (int g = 0; g < n; g++) {
		cout << next[g]<<" ";
	}
	
}

7.稀疏矩阵的打印输出

【问题描述】

 若一个稀疏矩阵A中的非零元素

image.png

以三元组的形式按照行优先的次序存储在三元组顺序表中,则打印输出对应的稀疏矩阵。

【输入形式】

输入的第一行三个数据分别为矩阵的行数mu、列数nu、非零元素值的个数tu,以空格间隔;

接下来共tu行,每行各三个数据,分别是非零元素的行标、列标、数值,以空格间隔。

【输出形式】三元组对应的稀疏矩阵。(每行中的元素中间以5个空格隔开)

【样例输入】

5 4 5

1 1 3

1 4 7

2 3 -1

3 1 2

5 4 -8

【样例输出】

3     0     0     7

0     0    -1     0

2     0     0     0

0     0     0     0

0     0     0    -8

#include  <iostream>
using  namespace  std;
const  int  MaxSize = 100;
/*三元组结构体*/
template  <class  DataType>
struct  element {
    int  row, col;  //非零元素的行、列
    DataType  item;  //非零元素值
};

template  <class  DataType>
class  SparseMatrix {
public:
    SparseMatrix();
    void  printMatrix();
    void  printSparseMatrix();
    void  trans2(SparseMatrix<DataType>& B);
private:
    element<DataType>  data[MaxSize];  //存储三元组表
    int  mu, nu, tu;  //分别表示稀疏矩阵的行数、列数、非零元素的个数
};
/*三元组顺序表的构造*/
template  <class  DataType>
SparseMatrix<DataType>::SparseMatrix()
{
    int  row, col, num;
    cin >> row >> col >> num;  //稀疏矩阵的行数、列数
    mu = row;
    nu = col;
    tu = num;  //存储时从0开始
    for (int k = 0; k < num; ++k) {
        int  i, j, temp;
        cin >> i >> j >> temp;
        data[k].row = i;
        data[k].col = j;
        data[k].item = temp;
    }
}

/*稀疏矩阵的打印*/
template  <class  DataType>
void  SparseMatrix<DataType>::printMatrix()
{
    int a[100][100];
    int i, j;
    for (i = 0; i < mu; i++) {
        for (j = 0; j < nu; j++) {
            a[i][j] = 0;
        }
    }
    for (int k = 0; k <tu; k++) {
        a[data[k].row-1][data[k].col-1] = data[k].item;
    }
    for (i = 0; i < mu; i++) {
        for (j = 0; j < nu; j++) {
            cout<<a[i][j]<<"     ";
        }
        cout << endl;
    }

}


int  main()
{
    SparseMatrix<int>  A;
    A.printMatrix();
    return  0;
}

 8.矩阵的鞍点

【问题描述】   若在一个矩阵A中存在一个元素

Snipaste_2019-10-07_20-19-50.png

该元素是第i行的最小值元素且又是第j列的最大值元素,则称此元素是该矩阵的一个鞍点。假设以二维数组存储矩阵,设计算法求矩阵A的所有鞍点(输出鞍点的数值、行号、列号),若矩阵中不存在鞍点,应给出相应的信息(No answer)。

【输入形式】

输入的第一行两个数据分别为矩阵的m,n值,以空格间隔;

第二行为整型数组中的所有元素,以空格间隔,按行来保存数据。

【输出形式】输出所有的马鞍点,包括鞍点值,以及所在行和列;若无,打印 no。

【样例输入】

5 5

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

【样例输出】

3 2 2

3 4 2

3 5 2

【样例说明】输入5*5的矩阵,第一行的数据为1 2 3 4 5,第二行 7 3 4 5 6,以此类推:

1 2 3 4 5 

7 3 4 5 6 

2 1 5 4 3 

5 3 6 5 4 

5 3 6 5 4

输出本数组中的三个马鞍点3(2行2列)   3(4行2列) 3(5行2列)。

#include  <iostream>
using  namespace  std;
void  saddlePoint(int** A, int  n, int  m)
{
    int i, j;
    int max[10] = { 0 }, min[10] = { 0 };//存放每行最小值,每列最大值
    int MIN, MAX;
    for (i = 1; i <=n; i++) {//每行遍历
        MIN = A[i][1];//每行第一个
        for (j = 1; j <=m; j++) {//每列遍历
            if (MIN > A[i][j]) {
                MIN = A[i][j];
            }
        }
        min[i] = MIN;//求每行最小值,并存入数组
    }
    for (j = 1; j <=m; j++) {//每行遍历
        MAX = A[1][j];//每列第一个
        for (i = 1; i <=n; i++) {//遍历每一行
            if (MAX < A[i][j]) {
                MAX = A[i][j];
            }
        }
        max[j] = MAX;//求每列最大值,并存入数组
    }
    int flag = 0;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (A[i][j] == min[i] && A[i][j] == max[j]) {//遍历寻找同时满足的值
                flag = 1;
                cout << A[i][j] << " " << i << " " << j << endl;
            }
        }
        
    }
    if (flag == 0) cout << "No answer";
}
int  main()
{
    int  n, m;
    cin >> n >> m;
    int** arr = new  int* [n + 1];
    for (int i = 0; i <= n + 1; ++i)
        arr[i] = new  int[m + 1];

    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            cin >> arr[i][j];

    saddlePoint(arr, n, m);
    return  0;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yoin.

感谢各位打赏!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值