トピック:
制限時間:時間の1000msで単一のポイント:1000ミリ秒メモリの制限:256MBの説明
遺伝子工学の実験を行い、小さな、小さなハイホー。Kの配列は、配列からなるこの塩基組成Kの上にDNA塩基を最後尾のように、長さNのそれらのDNA配列の一部を変更する同じ。2つの塩基の最後2つの塩基の上面が「AC」になるように、例えば、配列「ATCGATAC」とK = 2は、第2のベースは、「C」によって修飾されてもよいです。当然のことながら、変更する他の方法としては、例えば、「T」の最後のベースに、直接2人の前に、存在し、最後尾の2つの塩基は「GG」に変更されます。
すべてのメソッドを知るためにハイホー小さな、小さな希望する方法は、塩基の数を変更するために少なくとも修正拠点が必要です。
最初の行の入力が整数T(1 <= T <= 10)が含まれ、テストデータの数を表します。
2つの行を含む各テストケースは、最初の行は「ATCG」4つの大文字の長さは、N(1 <= N <=である 1000) 文字列。第二行は、整数Kである(1
<= K <= N)。塩基の出力データ出力最小数の各セットのために変更されます。
サンプル入力
2
ATCGATAC
2
ATACGTCT 6サンプル出力
1
3
考え
私は、複雑なを開始したいです。実際には、この問題は法律を見つけるために、特定を通じて非常に単純な形で解決することができます。ここも考えるようになったし、簡単な方法洗練されたアプローチを導入しました。
再帰(愚かな方法):
長さNの各列について、それが最初のK-K文字列N-(NK)の後に文字のストリングと等しくなるように、その正面K-(NK)文字ように、長さにすることができます問題へのK-(NK)文字の後に等しいストリング。ここで、操作n番目、nが前N-(NK)にサブストリングなどの文字を、N個の文字を取るために、奇数である場合、nが偶数である場合に、としてN-(NK)文字数Nの文字を取りますストリング。
2再帰アップ* K <= Nは、いかなる文字列は、このオーバーラップフラグビット列ことなく、同一の部分に重なるように、およびNK文字のたびに割り当てを除去する必要がない場合には処理をフォールバックここで録音Nの文字が同じである必要があります。現在の最高周波数文字を変更するために必要な単語の数が表示されたときに、ある-最後に、すべての文字のため、合計数を最高周波数を見つけるために同じ位置にする必要があります。回全症例の累積数は、結果が得られ。
この方法は、今、その時は愚かな感じ現れ、あまりにも複雑であるが、それはまだ、彼は非常に巧妙であると感じました。。。
法律を見つける方法:
見つけることができ、法律を探し、この質問は、人間の本質は同じリピーターであるとして事実がNKの長さサブストリングのサイクルは、後に最終的な結果を修正するために必要とされます。
ビット0から、それぞれNKのビット順序は同一の符号を付し。例えば、それによって1,2,3-標識記号のN = 10、K = 7、各マークシンボルの位置は0,1,2 1,2,3 3,4,5位置を仮定類推により、代表後の同じマークは、対応する文字が同じである必要があります修正します。完了マークの後数をカウントするために、上記の再帰的メソッドの実装の最終ステップをマーク。
関連機能:
memsetの(開始アドレス、0、サイズ):0に空間サイズからアドレス値を開始して、配列を初期化するために使用されます。ヘッダーの#include <memory.h>
三項演算子は:式の括弧内に追加される、同一の優先順位に等しいです。
可能性のある問題:
図1に示すように、従来の方法または再帰MLE TLEは:K = Nの特別な場合を考慮していない場合、無限ループ、日本語文にK = Nの添加に入ります。
2、RE:配列サイズは十分開いて、対象が1000の長さが、ジョブのような2000人のルックスを開くために、実際の必要性と言うこともできます。
ACコード
再帰:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<memory.h>
using namespace std;
int name[10000];
int num;
string str;
void
digui(int begin, int end, int K, int flag) {
int shorter = end - begin + 1 - K;
if ((end - begin + 1) / 2 >= K) {
int i = 0;
for (; i < K; i++) {
name[begin + i] = i + 1;
name[end - K + 1 + i] = i + 1;
}
for (; i <= end - begin - K; i++) {
name[begin + i] = i + 1;
}
num = i;
return;
}
else {
flag == 1 ? end -= shorter : begin += shorter;
digui(begin, end, K - shorter, -flag);
if (flag == 1) {
for (int i = 0; i < shorter; i++) {
name[end - i + shorter] = name[end - i];
}
}
else {
for (int i = 0; i < shorter; i++) {
name[begin + i - shorter] = name[begin + i];
}
}
return;
}
}
int main() {
int T;
cin >> T;
while (T--) {
memset(name, 0, 10000);
cin >> str;
int K;
cin >> K;
int count = 0;
if (K == str.size()) {
cout << 0 << endl;
continue;
}
digui(0, str.size() - 1, K, 1);
//统计次数
for (int i = 1; i < num + 1; i++) {
int a, t, c, g;
a = t = c = g = 0;
for (int j = 0; j < str.size(); j++) {
if (name[j] == i) {
switch (str[j]) {
case 'A':a++; break;
case 'T':t++; break;
case 'C':c++; break;
case 'G':g++; break;
}
}
}
int max1 = c > g ? c : g;
int max2 = a > t ? a : t;
count += a + t + c + g - (max1 > max2 ? max1 : max2);
}
cout << count << endl;
}
return 0;
}
法律を見つける方法:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<memory.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int name[10000];
memset(name, 0, 10000);
int num;
string str;
cin >> str;
int K;
cin >> K;
int count = 0;
if (K == str.size()) {
cout << 0 << endl;
continue;
}
//哪些位置应该一样
int begin = 0, end = str.size() - 1;
int flag = 1;
int shorter = str.size() - K;
for (int i = 0; i < str.size(); i++) {
name[i] = i % shorter + 1;
}
num = shorter;
//统计次数
for (int i = 1; i < num + 1; i++) {
int a, t, c, g;
a = t = c = g = 0;
for (int j = 0; j < str.size(); j++) {
if (name[j] == i) {
switch (str[j]) {
case 'A':a++; break;
case 'T':t++; break;
case 'C':c++; break;
case 'G':g++; break;
}
}
}
int max1 = c > g ? c : g;
int max2 = a > t ? a : t;
count += a + t + c + g - (max1 > max2 ? max1 : max2);
}
cout << count << endl;
}
return 0;
}