洛谷:P5587 打字練習

大便上的牙印發表於2020-11-06

題目描述
R 君在練習打字。

有這樣一個打字練習網站,給定一個範文和輸入框,會根據你的輸入計算準確率和打字速度。可以輸入的字元有小寫字母、空格和 .(英文句號),輸入字元後,游標也會跟著移動。

輸入的文字有多行,R 君可以通過換行鍵來換行,換行後游標移動到下一行的開頭。

R 君也可以按退格鍵(為了方便,退格鍵用 < 表示),以刪除上一個打的字元,並將游標回移一格。特殊的,如果此時游標已經在一行的開頭,則不能繼續退格(即忽略此時輸入的退格鍵)。

網站的比較方式遵循以下兩個原則:

逐行比較,即對於範文和輸入的每一行依次比較,不同行之間不會產生影響,多餘的行會被忽略。
逐位比較,即對於兩行的每一個字元依次比較,當且僅當字元相同時才會被算作一次正確,否則會被算作錯誤。計算答案時,只統計相同的字元個數。
需要注意的是,Enter鍵不會被計入正確的字元個數。

R 君看到網站上顯示他花了 T 秒完成了這次的打字遊戲,請你計算出他的 KPM(Keys per minutes,每分鐘輸入的字元個數),答案四捨五入保留整數部分。

輸入格式
R 君會依次告訴你網站的範文,他的輸入和花費的時間。

其中範文和輸入將會這樣讀入:給定若干行字串,以單獨的一行 EOF 結束,其中 EOF 不算入輸入的文字。

最後一行一個整數 T,表示他打字花費了 T 秒。

可以參考樣例輸入輸出檔案和樣例解釋輔助理解。

輸出格式
一行一個整數,表示 KPM。

輸入輸出樣例
輸入 #1

hello world.
aaabbbb
x
EOF
heelo world.
aaacbbbb
y<x
EOF
60

輸出 #1

18

說明/提示
樣例解釋
第一行的正確字元數為 11。
第二行的正確字元數為 6,錯誤的字元 c 仍會佔據一個位置。
第三行的正確字元數為 1,R 君使用退格鍵刪除了被打錯的字元 y

資料範圍
對於 20% 的資料,不存在換行鍵。
對於 40% 的資料,不存在退格鍵。
對於 100% 的資料,T≤1e3
,保證每個文字段的總字元數(包括換行)不超過 1e5個且總行數不超過 1e4。

思路:
範文中也有退格,而且有兩種比較方式,逐行比較和逐位比較,
借鑑洛谷中的題解來記錄此題:

#include<iostream> 
#include<string>
#include<algorithm>

using namespace std;
string a[100001], b[100001];// a是第一個樣本,b是第二個樣本。
int num = 0, num2 = 0, num1, sum, t;
int main()
{
	while (1)
	{
		getline(cin, a[num]);
		if (a[num] == "EOF") break; // 輸入碰到‘EOF’就直接break掉
		num++;
	}
	while (1)
	{
		getline(cin, b[num1]);
		if (b[num1] == "EOF") break;
		num1++;
	}
	cin >> t;// 時間
	int num2 = min(num, num1);// 根據題面意思,比較時多餘的行被忽略,因此取num和num1的最最小值。
	for (int i = 0; i<num2; i++)
	{
		char aa[100001], bb[100010];
		int ans1 = 0, ans2 = 0, s1 = a[i].size(), s2 = b[i].size();// ans1、ans2分別表示第一個樣本和第二個樣本的游標的位置
		for (int j = 0; j<s1; j++)
		{
			if (a[i][j] == '<')// 如果是退格,游標不用加還要往後移。
			{
				ans1 = max(0, ans1 - 1);
				continue;
			}
			aa[ans1] = a[i][j];// 不是退格隨著輸入往後加
			ans1++;
		}
		for (int j = 0; j<s2; j++)
		{
			if (b[i][j] == '<')
			{
				ans2 = max(0, ans2 - 1);
				continue;
			}
			bb[ans2] = b[i][j];
			ans2++;
		}
		for (int j = 0; j<min(ans1, ans2); j++)// 逐行比較,去掉多餘的列
		{
			if (aa[j] == bb[j]) sum++;
		}
	}
	int k = ((sum*1.0) * 60) / (t*1.0);
	cout << k;// round()四捨五入輸出。
	return 0;
}