1. 程式人生 > 其它 >CF544A Set of Strings 題解

CF544A Set of Strings 題解

CF544A Set of Strings 題解

Content

有一個長為 \(n\) 的字串 \(q\),試問能否將其劃分為 \(k\) 個子串,使得每個子串的首字母都不相等,可以的話輸出 \(\texttt{YES}\) 並輸出任意一個方案,否則輸出 \(\texttt{NO}\)

資料範圍:\(1\leqslant n\leqslant 100,1\leqslant k\leqslant 26\)

Solution

我們可以考慮這樣的一個流程:

  • 輸入字串後,一個一個去掃。
  • 如果有一個之前沒有出現過的字母,就立刻建立新的一個空子串。之後,將當前字元加入到當前子串裡面(有可能是之前已經有字母在裡面的子串,而不是新的子串)。

看不懂的話可以參照下面這個資料:

10
whenthereisawillthereisaway

下面是模擬過程——

  • 從第一個字元 \(\texttt{w}\) 開始。
  • 建立第一個空子串。將第一個字元加入到這個子串裡面,這時,第一個子串是 \(\texttt{w}\)
  • 掃到第二個字元 \(\texttt{h}\),前面沒有出現過,則建立第二個空子串,並將第二個字元加入到這個子串裡面,這時,第二個子串是 \(\texttt{h}\)
  • 掃到第三個字元 \(\texttt{e}\),前面沒有出現過,則建立第三個空子串,並將第三個字元加入到這個子串裡面,這時,第三個子串是 \(\texttt{e}\)
  • 掃到第四個字元 \(\texttt{n}\)
    ,前面沒有出現過,則建立第四個空子串,並將第四個字元加入到這個子串裡面,這時,第四個子串是 \(\texttt{n}\)
  • 掃到第五個字元 \(\texttt{t}\),前面沒有出現過,則建立第五個空子串,並將第五個字元加入到這個子串裡面,這時,第五個子串是 \(\texttt{t}\)
  • 掃到第六個字元 \(\texttt{h}\),前面出現過,則將第六個字元加入到第五個子串裡面,這時,第五個子串是 \(\texttt{th}\)

以此類推,這樣,最後的十個子串分別是 \(\texttt{w}\)\(\texttt{h}\)\(\texttt{e}\)\(\texttt{n}\)\(\texttt{the}\)

\(\texttt{re}\)\(\texttt{i}\)\(\texttt{s}\)\(\texttt{awi}\)\(\texttt{llthereisaway}\)

你也可以試試 \(k=17\) 的情況,此時應該輸出 \(\texttt{NO}\),具體請讀者自行模擬。

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;

int k, num;
string s, spre[107];
map<char, int> vis;

int main() {
	scanf("%d", &k);
	cin >> s;
	num = 1;
	spre[num] += s[0];
	vis[s[0]] = 1;
	for(int i = 1; i < s.size(); ++i) {
		if(!vis[s[i]]) {
			num++;
			if(num > k) {
				for(int j = i; j < s.size(); ++j)
					spre[num - 1] += s[j];
				break;
			}
			vis[s[i]] = 1;
		}
		spre[num] += s[i];
	}
	if(num < k)	return printf("NO"), 0;
	else {
		puts("YES");
		for(int i = 1; i <= num; ++i)
			cout << spre[i] << endl;
	}
}