1. 程式人生 > >演算法競賽入門經典字串推薦題目

演算法競賽入門經典字串推薦題目

題目

UVA 401 Palidromes

分析

  1. 鏡面字串應關於中間位置鏡面對稱,特別地,若中間位置為一字元則該字元也應自鏡面對稱,所以字串的字元個數的奇偶需要考量.
  2. 因為數字0和字母O可視為一致,因此僅字母O是合法輸入,即不必考慮輸入資料包含數字0.
  3. 注意格式:每輸出一行資料,應跟隨輸出一空行.

程式碼

#include <stdio.h>
#include <string.h>

int is_palindrome(char* str, int len)
{
    int i;
    for (i = 0; i < len/2; i++)
        if
(*(str + i) != *(str + (len-1) - i)) return 0; return 2; } int is_mirrored(char* str, int len) { const char* ch = "AEHIJLMOSTUVWXYZ12358"; const char* re = "A3HILJMO2TUVWXY51SEZ8"; int i, j; for (i = 0; i < len/2+1; i++) { for (j = 0; j < 21; j++) { if
(*(str + i) == *(ch + j)) { if (*(str + (len-1) - i) != *(re + j)) return 0; break; } } if (j == 21) return 0; } return 1; } int main(void) { char str[25]; int len = 0; while (scanf("%s", str) != EOF) { printf("%s"
, str); len = strlen(str); switch (is_palindrome(str, len) | is_mirrored(str, len)) { case 0: /* 00 */ printf(" -- is not a palindrome."); break; case 2: /* 10 */ printf(" -- is a regular palindrome."); break; case 1: /* 01 */ printf(" -- is a mirrored string."); break; case 3: /* 11 */ printf(" -- is a mirrored palindrome."); break; } printf("\n\n"); } return 0; }

UVA 10010 Where’s Waldorf?

分析

  1. 所需搜尋的模式必定出現且僅出現一次,但大小寫不敏感.
  2. 先遍歷確定首字母,再進入搜尋,因為模式僅沿八個方向中的固定一個,所以可以滾一遍八方向.

程式碼

#include <stdio.h>
#include <string.h>

int m, n, x, y;
char map[55][55];
int next[8][2] = {{1,1}, {1,0}, {0,1}, {1,-1}, {-1,1}, {-1,0}, {0,-1}, {-1,-1}};

void search(char* s)
{
    int pos, nx, ny, i, j, k;
    for (i = 1; i <= m; i++)
        for (j = 1; j <= n; j++)
            if (map[i][j] == s[0])
                for (k = 0; k < 8; k++) {
                    pos = 0;
                    nx = i;
                    ny = j;
                    while (s[pos] && map[nx][ny]==s[pos]) {
                        nx += next[k][0];
                        ny += next[k][1];
                        pos++;
                    }
                    if (!s[pos]) { /* base */
                        x = i;
                        y = j;
                        return;
                    }
                }
}

int main(void)
{
    int t, i, j, k;
    char str[55];
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &m, &n);
        for (i = 1; i <= m; i++) {
            scanf("%s", str);
            for (j = 1; j <= n; j++)
                map[i][j] = tolower(str[j-1]);
        }
        scanf("%d", &k);
        while (k--) {
            scanf("%s", str);
            j = strlen(str);
            for (i = 1; i <= j; i++)
                str[i-1] = tolower(str[i-1]);
            search(str);
            printf("%d %d\n", x, y);
        }
        if (t) printf("\n");
    }
    return 0;
}

UVA 10361 Automatic Poetry

分析

  1. 字串總分分合合,而我們卻越恨越深.

程式碼

#include <stdio.h>
#define MAXN 100+10

int main(void)
{
    int t, i, j;
    char l1[MAXN], l2[MAXN], s[MAXN], s1[MAXN], s2[MAXN], s3[MAXN], s4[MAXN], s5[MAXN]; 
    scanf("%d", &t);
    getchar();
    while (t--) {
        fgets(l1, MAXN, stdin);
        fgets(l2, MAXN, stdin);

        for (i = 0, j = 0; l1[i] != '<'; i++, j++) s1[j] = l1[i];
        s1[j] = '\0';
        for (i += 1, j = 0; l1[i] != '>'; i++, j++) s2[j] = l1[i];
        s2[j] = '\0';
        for (i += 1, j = 0; l1[i] != '<'; i++, j++) s3[j] = l1[i];
        s3[j] = '\0';
        for (i += 1, j = 0; l1[i] != '>'; i++, j++) s4[j] = l1[i];
        s4[j] = '\0';
        for (i += 1, j = 0; l1[i] != '\n'; i++, j++) s5[j] = l1[i]; 
        s5[j] = '\0';
        for (i = 0, j = 0; l2[i] != '.'; i++, j++) s[j] = l2[i]; 
        s[j] = '\0';

        printf("%s%s%s%s%s\n", s1, s2, s3, s4, s5); 
        printf("%s%s%s%s%s\n", s, s4, s3, s2, s5);
    }
    return 0;
}

UVA 537 Artificial Intelligence?

分析

  1. 由於=的確定性,用其作關鍵字元,獲得其前一位的物理量,獲得數值(可利用string.h提供的atof()方法),再獲得之後的計量單位,對數值進行處理.
  2. 判斷哪一個物理量需要計算,輸出其計算結果.

程式碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 250

int main(void)
{
    float data[3], n;
    int flag[3]; /* P, U, I */
    int t, i, j, k;
    char buf[MAXN];
    char tmp[10];

    scanf("%d", &t);
    getchar();

    for (i = 0; i < t; i++) {
        memset(flag, 0, sizeof(flag));
        memset(data, 0, sizeof(data));
        fgets(buf, MAXN, stdin);
        for (j = 0; j < strlen(buf);) {
            /*if (!(flag[0]||flag[1]) || !(flag[1]||flag[2]) || !(flag[0]||flag[2]) )*/
                if (buf[j] == '=') {
                    for (k = 0; (buf[j+1+k] >= '0' && buf[j+1+k] <= '9') || buf[j+1+k] == '.'; k++)
                        tmp[k] = buf[j+1+k];
                    tmp[k] = '\0';
                    n = atof(tmp);
                    if (buf[j+1+k] == 'm')
                        n = n * 0.001;
                    else if (buf[j+1+k] == 'k')
                        n = n * 1000;
                    else if (buf[j+1+k] == 'M')
                        n = n * 1000000;
                    if (buf[j-1] == 'P') {
                        data[0] = n;
                        flag[0] = 1;
                    } else if (buf[j-1] == 'U') {
                        data[1] = n;
                        flag[1] = 1;
                    } else if (buf[j-1] == 'I') {
                        data[2] = n;
                        flag[2] = 1;
                    }
                    j += k;
                } else {
                    j++;
                }
        }

        printf("Problem #%d\n", i+1);
        for (j = 0; j < 3; j++) {
            if (flag[j] == 0) {
                if (j == 0) {
                    printf("P=%.2fW\n", data[1]*data[2]);
                } else if (j == 1) {
                    printf("U=%.2fV\n", data[0]/data[2]);
                } else {
                    printf("I=%.2fA\n", data[0]/data[1]);
                }
                break;
            }
        }
        if (i != t-1) printf("\n");
    }
    return 0;
}

UVA 409 Excuses, Excuses!

分析

  1. 儲存藉口(excuses)的關鍵詞用於後面的匹配.
  2. 獲取每一句藉口的每一個單詞,與關鍵詞匹配,並存儲該藉口中關鍵詞的出現次數.
  3. 注意:輸出關鍵詞出現次數最多的藉口,但可能不止一個.

程式碼

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
    int k, e, a[25], max, t = 1, i, j, m, n;
    char word[25][25], excuse[25][75], ch[75];

    while (scanf("%d%d", &k, &e) != EOF) {
        getchar();
        for (i = 0; i < k; i++) {
            scanf("%s", word[i]);
            getchar();
        }
        memset(a, 0, sizeof(a));
        max = 0;
        for (i = 0; i < e; i++) {
            fgets(excuse[i], 75, stdin);
            for (j = 0; j < strlen(excuse[i]);) {
                for (m = 0; isalpha(excuse[i][j+m]); m++)
                    ch[m] = tolower(excuse[i][j+m]);
                if (m) {
                    ch[m] = '\0';
                    /* printf("catch:%s\n", ch);*/
                    j += m;
                    for (n = 0; n < k; n++) {
                        if (strcmp(ch, word[n]) == 0) {
                            a[i]++;
                            break;
                        }
                    }
                } else {
                    j++;
                }
            }
            max = max > a[i]? max: a[i];
            /*printf("%d\n", a[i]);*/
        }
        printf("Excuse Set #%d\n", t++);
        for (i = 0; i < e; i++)
            if (a[i] == max)
                printf("%s", excuse[i]);
        printf("\n");
    }
    return 0;
}

UVA 10878 Decode the tape

分析

  1. 打孔紙帶可能指向二進位制,可以嘗試用二進位制的方式思考,假設打孔表示1,並且得到的數恰又是ASCII碼,輸出結果得到驗證,紙帶已解.

程式碼

#include <stdio.h>
#include <string.h>

int main(void)
{
    char tape[15];
    int i, r;
    int f[] = {0, 0, 64, 32, 16, 8, 0, 4, 2, 1, 0};
    while (fgets(tape, 15, stdin)) {
        r = 0;
        for (i = 2; i < 10; i++)
            if (tape[i] == 'o')
                r += f[i];
        if (r != 0) putchar(r);
    }
    return 0;
}

UVA 10815 Andy’s First Dictionary

分析

  1. 逐字元清洗,獲得字典.
  2. 使用類qsort()快速排序等方法避免超時.

程式碼

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

char word[27050][250];

int comp(const void* a, const void* b)
{
    return strcmp((char*)a, (char*)b);
}

int main(void)
{
    char ch;
    int i = 0, j = 0;
    while ((ch = getchar()) != EOF ) {
        if (isalpha(ch)) {
            word[i][j++] = tolower(ch);
        } else if (j) {
            word[i][j] = '\0';
            i++;
            j = 0;
        }
    }
    qsort(word, i, sizeof(word[0]), comp);
    for (j = 0; j < i; j++)
        if (strcmp(word[j], word[j+1]))
            printf("%s\n", word[j]);
    return 0;
}

UVA 644 Immediate Decodability

分析

  1. 兩兩比較一個code是否是另一code的字首,如果是則說明存在二義性,即不可立即解碼.

程式碼

#include <stdio.h>
#include <string.h>

int is_prefix(const char* a, const char* b)
{
    if (strlen(a) > strlen(b))
        return is_prefix(b, a);
    int i;
    for (i = 0; i < strlen(a)-1; i++)
        if (*(a+i) != *(b+i))
            return 0;
    return 1;
}

int main(void)
{
    char bit[10][15];
    char buf[15];
    int t, n = 0, i, j, flag;
    for (t = 1; fgets(buf, 15, stdin); ) {
        if (buf[0] == '9') {
            flag = 0;
            for (i = 0; i < n; i++) {
                for (j = i+1; j < n; j++) {
                    if  (is_prefix(*(bit+i), *(bit+j))) {
                        printf("Set %d is not immediately decodable\n", t);
                        flag = 1;
                        break;
                    }
                }
                if (flag) break;
            }
            if (!flag) printf("Set %d is immediately decodable\n", t);
            n = 0;
            t += 1;
        } else {
            strcpy(bit[n++], buf);
        }
    }
    return 0;
}

UVA 10115 Automatic Editing

分析

  1. 依次利用給定規則,將字串滾一遍.
  2. 拼接字串(disgusting!).

程式碼

#include <stdio.h>
#include <string.h>

int main(void)
{
    char fid[15][90], rep[15][90], str[300], tmp[300];
    int t, i, j, k, m;
    while (scanf("%d", &t) && t) {
        getchar();
        for (i = 0; i < t; i++) {
            fgets(fid[i], 90, stdin);
            fgets(rep[i], 90, stdin);
        }
        fgets(str, 90, stdin);
        for (j = 0; j < t; j++) {
            for (i = 0; i < strlen(str)-1;) {
                for (k = 0; k < strlen(fid[j])-1; k++)
                    if (str[i+k] != fid[j][k])
                        break;
                if (k == strlen(fid[j])-1) {
                    memset(tmp, 0, sizeof(tmp));
                    for (m = 0; m < i; m++) tmp[m] = str[m];
                    for (m = 0; m < strlen(rep[j])-1; m++) tmp[i+m] = rep[j][m];
                    for (m = 0; m <= strlen(str) - strlen(fid[j]); m++) tmp[i+strlen(rep[j])-1+m] = str[i+strlen(fid[j])-1+m];
                    strcpy(str, tmp);
                    i = 0;
                } else
                    i++;
            }
        }
        printf("%s", str);
    }
    return 0;
}