Bài tập về chuỗi

Giúp em định hướng cách làm bài này với. Em xin cảm ơn!

  1. 2 vòng lặp. Lặp (1) từng ký tự trong S1 để so sánh với ký tự đàu trong S2. Nếu giống nhau thì nhảy vào lặp (2) để so sánh tiếp. Sau lặp (2) mà các ký tự hoàn toàn giống nhau thì xong! :+1:
  2. Tách từng từ theo dấu cách (ký tự khoảng trắng) rồi tính độ dài từng từ. 1 vòng lặp.
    :smiling_imp:
4 Likes

Bài 1 như trên :slight_smile:
Bài 2 xác định kí tự ngăn cách hai từ (có dấu câu không? :smiley: ) rồi lấy độ dài từ tại đó. Chú ý trường hợp nhiều kí tự.

5 Likes

“Không dùng hàm có sẵn” :slight_smile:

3 Likes

Câu 1. Từ ý tưởng của anh thì em viết ra như thế này, đã test thử và đúng. Anh xem thử có thể cải tiến hay chỉnh sửa chỗ nào cho hay hơn và dễ hiểu đc không ạ ?

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

void NhapChuoi(string& s)
{
	cout << "Nhap chuoi : ";
	getline(cin, s);
}

/* Cho Check = false, duyệt từng phần tử của chuỗi s1, tại vị trí s1[i] = kí tự đầu tiên
của s2 thì cho Check = true, tiếp tục duyệt s1[++i] vs từng phần tử của s2. Nếu có phần
tử khác nhau thì Check = false, thoát vòng lặp, tiếp tục tăng i
*/
bool KiemTra(string s1, string s2, int& vt)
{
	bool Check = false;
	for (int i = 0; i < s1.size(); i++)
	{
		
		if (s1[i] == s2[0])
		{
			Check = true;
			for (int j = 1; j < s2.size(); j++)
			{
				if (s1[++i] != s2[j]) {
					Check = false;
					break;
				}
			}
			// Nếu Check = true thì s2 nằm trong s1, lúc này i = i ban đầu + s2.size()			
			if (Check) vt = i + 1 - (s2.size() - 1);
		}
	}
	return Check;
}

int main()
{
	string s1, s2;
	int vt;
	NhapChuoi(s1);
	NhapChuoi(s2);
	bool ktra = KiemTra(s1, s2, vt);
	if (ktra) cout << "Chuoi S2 nam trong S1 tai vi tri " << vt;
	else cout << "S2 khong nam trong S1";
	return 0;
}

Bạn làm cơ bản vậy là được.
Đúng như ý của bạn, hàm thực hiện kiểm tra cần “cải tiến” nhiều chỗ.

  1. Kết quả trả về của hàm, bạn nên trả về luôn là vị trí tìm được. >=0 có nghĩa là tìm được và đó cũng là giá trị vị trí tìm được, -1 có nghĩa là không tìm được.
    Nghĩa là bỏ tham số cuối đi, nó sẽ trở thành giá trị trả về.
    int KiemTra(string s1, string s2).
  2. Bạn không cần tính toán vị trí tìm được trong hàm một cách phức tạp vậy đâu. Chỉ cần lưu giá trị ngay sau điều kiện if.
    vt = i.
  3. Cuối hàm, dựa vào biến Check mà bạn sẽ trả về vt hay -1.
    return Check ? vt : -1;
  4. Đề phòng trường hợp biến lặp (ij) chạy quá giới hạn độ dài của mỗi chuỗi.
  5. if (s1[++i] != s2[j]) biến i bị thay đổi trong vòng lặp 2. Không ổn!
4 Likes

Câu 2. Anh có thể giải thích rõ hơn hoặc code luôn được không ạ, hơi trừu tượng nên em chưa hiểu.
Ý tưởng của em là như thế này :

// đếm số lần xuất hiện của kí tự n trong chuỗi
int DemSoLanXuatHien(string& s, char n)
{
	int dem = 0;
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i] == n) dem++;
	}
	return dem;
}
// đếm số lượng phần tử trong chuỗi xuất hiện nhiều hơn n lần
int DemTu(string s, int n)
{
	int dem = 0;
	for (int i = 0; i < s.size(); i++)
	{
		if (DemSoLanXuatHien(s, s[i]) > n) {
			dem++;
		}
	}
	return dem;
}

Nhưng mà nó lại sai
VD : Nguyễn Văn A. nhập n = 2.
Nó sẽ đếm kí tự n đầu tiên, rồi những n phí sau nó cũng đếm, em chưa biết xử lí như thế nào.
Anh có thể sửa giúp em hoặc trình bày code của anh đc không ạ, em xin cảm ơn !

Câu 2 này bạn đi sai hướng rồi!
Mình đã hướng dẫn bạn phía trên. Nên chú ý rằng: mình có nhắc đến dấu cách (khoảng trắng - ' ').

3 Likes

câu 2. Cho em hỏi ngay sau if nào vậy anh ?
câu 4. Em không hiểu cho lắm, i < s1.size()j < s2.size() thì sao chạy quá giới hạn đc ạ ?
câu 5. Em suy luận như này : nếu mà s1[i] == s2[0] thì sẽ chạy vào vòng lặp 2. lúc này i phải tăng lên để kiểm tra vs s2[j]. Nếu có s1[i] != s2[j] thì dừng vòng lặp, i tiếp tục tăng để chạy tiếp, thì nó cũng đâu có ảnh hưởng đến vòng lặp ngoài ?

Giờ thử nhập như sau xem kết quả còn đúng không nhé:

S1 = "abcdefsssssa"
S2 = "sssa"
3 Likes

Em test thử thì sai rồi anh ơi :frowning:
Anh viết code luôn giúp em đc k ạ, để em học hỏi, cảm ơn anh nhiều

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?