//#define DEBUG 1 //#define TRACE #include #include #include #include #include #include #define MAXN 200001 #define ABCLEN 27 #define DICLEN 51 using namespace std; struct ResStruct { virtual string toStr() = 0; }; struct DelChar : ResStruct { int code; int idx; DelChar(int index) : code(3), idx(index){} string toStr() { ostringstream oss; oss << code; oss << " "; oss << idx; return oss.str(); } }; struct InsertChar : ResStruct { int code; int idx; char letter; InsertChar(int index, char letter) : code(4), idx(index), letter(letter) {} string toStr() { ostringstream oss; oss << code << " " << idx << " " << letter; return oss.str(); } }; struct Reverse : ResStruct { int code, left, right; Reverse(int left, int right) : code(2), left(left), right(right) {} string toStr() { ostringstream oss; oss << code << " " << left << " " << right; return oss.str(); } }; // Problem Vars int n/* DNA length */, k/* alphabet length */, t/* operations */; int v/*dict Len*/; int charDiff[ABCLEN][ABCLEN]; char startSeq[MAXN], endSeq[MAXN], dict[DICLEN][MAXN]; char tmp[MAXN]; int difference[MAXN]; void readInput() { freopen("fixdna.in", "r", stdin); scanf("%d %d %d\n", &n, &k, &t); scanf("%s\n%s\n", startSeq, endSeq); for (int i = 0; i < k; ++i) { for (int j = 0; j < k; ++j) { scanf("%d", &charDiff[i][j]); } } scanf("%d\n",&v); for (int i = 0; i < v; ++i) { scanf("%s\n", dict[i]); } } int calcDiff(char * src, char * dst) { int res = 0; int len = strlen(src); for (int i = 0; i < len; ++i) { res += charDiff[src[i]-'a'][dst[i]-'a']; } return res; } inline int diff(char c, char b) {return charDiff[c-'a'][b-'a'];} inline void myReverse(char * s, int startPos, int endPos, int *oldVal, int *newVal) { *oldVal = *newVal = 0; for (int i = startPos, j = endPos; i < j; ++i, --j) { *oldVal += diff(s[i], endSeq[i]) + diff(s[j], endSeq[j]); swap(s[i],s[j]); *newVal += diff(s[i], endSeq[i]) + diff(s[j], endSeq[j]); } } /* returns the difference between result and desired seq */ vector oneByOneCharChanging(int leftMoves) { vector result = vector(); vector > sorted = vector > (); int ops =leftMoves/2; int len = strlen(startSeq); for (int i = 0; i < len; ++i) { sorted.push_back(make_pair(diff(tmp[i], endSeq[i]), i)); } sort(sorted.begin(), sorted.end()); for (int i = 0; i < ops; ++i) { int pos = sorted[len-1-i].second; result.push_back(new DelChar(pos)); result.push_back(new InsertChar(pos, endSeq[pos])); tmp[pos]=endSeq[pos]; } #ifdef DEBUG fprintf(stderr, " %d", calcDiff(tmp, endSeq)); #endif return result; } vector withReverse() { vector result = vector(); memcpy(tmp, startSeq, sizeof(startSeq)); //n/10 int len = n/10; int inc = 1; int cnt = 0; while (cnt < 10) { difference[0] = diff(tmp[0], endSeq[0]); for (int i = 1; i < n; ++i) { difference[i] = difference[i-1]+diff(tmp[i], endSeq[i]); } int ed = n-1; int bst = 0; int bsti = 0; for (; ed >= len; --ed) { int tmp11 = difference[ed] - difference[ed-len]; if (tmp11 >bst) { bst = tmp11; bsti = ed; } } int oldVal, newVal; myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); #ifdef TRACE1 fprintf(stderr, " oldVal:%d,newVal:%d",oldVal, newVal); #endif inc = oldVal - newVal; if (inc <= 0) { myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); break; } result.push_back(new Reverse(bsti-len, bsti)); cnt++; } //same as before but with n/20 len = n/20; inc = 1; cnt = 0; while (cnt < 20) { difference[0] = diff(tmp[0], endSeq[0]); for (int i = 1; i < n; ++i) { difference[i] = difference[i-1]+diff(tmp[i], endSeq[i]); } int ed = n-1; int bst = 0; int bsti = 0; for (; ed >= len; --ed) { int tmp11 = difference[ed] - difference[ed-len]; if (tmp11 >bst) { bst = tmp11; bsti = ed; } } int oldVal, newVal; myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); #ifdef TRACE1 fprintf(stderr, " oldVal:%d,newVal:%d",oldVal, newVal); #endif inc = oldVal - newVal; if (inc <= 0) { myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); break; } result.push_back(new Reverse(bsti-len, bsti)); cnt++; } //end n/20 //same as before but with n/30 len = n/30; inc = 1; cnt = 0; while (cnt < 30) { difference[0] = diff(tmp[0], endSeq[0]); for (int i = 1; i < n; ++i) { difference[i] = difference[i-1]+diff(tmp[i], endSeq[i]); } int ed = n-1; int bst = 0; int bsti = 0; for (; ed >= len; --ed) { int tmp11 = difference[ed] - difference[ed-len]; if (tmp11 >bst) { bst = tmp11; bsti = ed; } } int oldVal, newVal; myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); #ifdef TRACE1 fprintf(stderr, " oldVal:%d,newVal:%d",oldVal, newVal); #endif inc = oldVal - newVal; if (inc <= 0) { myReverse(tmp, bsti-len, bsti, &oldVal, &newVal); break; } result.push_back(new Reverse(bsti-len, bsti)); cnt++; } //end n/30 #ifdef DEBUG fprintf(stderr, " %d", calcDiff(tmp, endSeq)); #endif vector oneByOne = oneByOneCharChanging(t-result.size()); result.insert(result.end(),oneByOne.begin(), oneByOne.end()); return result; } void solve1() { freopen("fixdna.out", "w", stdout); vector res = withReverse(); int len = res.size(); printf("%d\n", len); for (int i = 0; i < len; ++i) { string forPrint = res[i]->toStr(); delete res[i]; printf("%s\n", forPrint.c_str()); } } int main(int argc, char *argv[]) { readInput(); #ifdef DEBUG fprintf(stderr, " %d", calcDiff(startSeq, endSeq)); #endif //cout << argc << endl; //for (int i = 0; i < argc; ++i) { // cout << argv[i] << endl; //} //system("fixdna.exe"); solve1(); return 0; }