#include #include #define MAX_N 100000 #define MAX_CHAR 26 #define NIL -1 short s[MAX_N + 1]; // + '\0' (NIL) int slen; // pos[i][j] este poziția celei de-a j-a apariție a caracterului i int pos[MAX_CHAR][MAX_N + 1]; // count[i] este numărul de caractere i int count[MAX_CHAR]; // seen[i] este numărul de caractere i deja văzute int seen[MAX_CHAR]; int mods[MAX_CHAR]; // mods[i] este numărul de modificatori i int minMod; // Modificatorul minim rămas void debug() { for (int i = 0; i < slen; i++) { putchar(s[i] + 'a'); } printf("\n"); for (int c = 0; c < MAX_CHAR; c++) { printf("%c (%d):", c + 'a', count[c]); for (int i = 0; i < 10; i++) { printf(" %d", pos[c][i]); } printf("\n"); } for (int c = 0; c < MAX_CHAR; c++) { printf("%d ", mods[c]); } printf("\n"); } int main() { FILE *fin = fopen("tensor.in", "r"); FILE *fout = fopen("tensor.out", "w"); int c = fgetc(fin), i = 0; while (islower(c)) { c -= 'a'; s[slen++] = c; pos[c][count[c]++] = i; c = fgetc(fin); i++; } s[slen] = NIL; c = fgetc(fin); minMod = MAX_CHAR; while (islower(c)) { c -= 'a'; mods[c]++; if (c < minMod) { minMod = c; } c = fgetc(fin); } int k = 0; // poziția curentă în s while (minMod < MAX_CHAR) { // Câtă vreme mai există modificatori // Determină prima poziție care nu poate fi eliminată cu modificatorii existenți int l = slen; for (c = 0; c < MAX_CHAR; c++) { if ((seen[c] + mods[c] < count[c]) && (pos[c][seen[c] + mods[c]] < l)) { l = pos[c][seen[c] + mods[c]]; } } // debug(); // printf("k %d l %d s[l] %c minMod %c\n", k, l, s[l] + 'a', minMod + 'a'); if (l == slen) { // Caută cel mai mare caracter pe care nu îl vom putea șterge (total impar). // Pentru cele mai mari ca el, păstrează doar câți modificatori avem nevoie // ca să putem șterge toate aparițiile din s. int maxMod = MAX_CHAR - 1; while ((maxMod >= 0) && ((count[maxMod] - seen[maxMod] + mods[maxMod]) % 2 == 0)) { mods[maxMod] = count[maxMod] - seen[maxMod]; maxMod--; } // printf("Final! maxMod %d\n", maxMod); if (maxMod < 0) { // Putem obține șirul vid, căci toate paritățile sunt pare k = slen; minMod = MAX_CHAR; } else { // Adaugă caracterul maxMod la sfârșitul lui s mods[maxMod] = count[maxMod] - seen[maxMod]; pos[maxMod][count[maxMod]++] = slen; s[slen++] = maxMod; s[slen] = NIL; } } else if (s[l] < minMod) { // printf("Tai de la %d la %d și accept %d\n", k, l - 1, l); // Taie pozițiile de la k la l - 1 for (i = k; i < l; i++) { mods[s[i]]--; seen[s[i]]++; } // Acceptă s[l] seen[s[l]]++; fputc(s[l] + 'a', fout); k = l + 1; } else if (s[l] > minMod) { // printf("Vărs de %d ori modificatorul %c\n", mods[minMod], minMod + 'a'); while (mods[minMod]) { fputc(minMod + 'a', fout); mods[minMod]--; } } else if (s[k] == minMod) { // Acceptă s[k] // printf("Accept s[%d] = %c\n", k, s[k] + 'a'); seen[s[k]]++; fputc(s[k] + 'a', fout); k++; } else { // s[k] trebuie să fie > minMod // Taie s[k] // printf("Tai s[%d] = %c\n", k, s[k] + 'a'); mods[s[k]]--; seen[s[k]]++; k++; } // Actualizează minMod, modificatorul minim disponibil while (minMod < MAX_CHAR && !mods[minMod]) { minMod++; } } while (k < slen) { fputc(s[k++] + 'a', fout); } fputc('\n', fout); fclose(fin); fclose(fout); return 0; }