[USACO] Calf Flac

    技术2022-05-19  19

     

    最初的想法:让i指向字符串的首端,j指向末端,然后对每一个i,j逐渐递减,然后对每一个递减的j,判断i到j这段字符串是否回文。这个白痴的想法最坏需要O(n3)的时间,虽然可以通过局部的优化,提前结束i,j的遍历以及回文的判断,可是对于第八个测试数据死活也过不了,时间超了不止一点两点,本机上跑用了4秒多,我擦嘞!

    上网搜索了一下提示,我的想法是从两边向中心靠拢,其实还可以从中心向两边延伸,这样只要遍历每个中心点,对每个中心点进行双向的搜索,时间复杂度就降为O(n2),可以接受了。遍历时注意分两种情况,abba和abcba的对称位置是不同的。。。

    实际编码时,明显感觉比原来的想法实现起来容易很多,少一层循环边界条件就少一些,出错几率就小一些,最后连TE再加上WA一共提交了7次,花了一天时间,你妹的!

    网上还有一种方法是把输入串翻转,然后求最长公共子串,这个没有具体细看,回头再说。。。

     


     

    /* ID: LANG: C TASK: calfflac */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define SZ 20000 int has_pal(char *txt, int len, int *low, int *high) { int n = 0; int i = *low; int j = *high; if(*high - *low == 2 && isalpha(txt[*high - 1]))//contribute wa once! n = 1; while(*low >=0 && *high < len) { if(!isalpha(txt[*low])) { (*low)--; continue; } if(!isalpha(txt[*high])) { (*high)++; continue; } if(tolower(txt[*low]) == tolower(txt[*high])) { i = *low; j = *high; (*low)--; (*high)++; n += 2; } else break; } *low = i; *high = j; return n; } int main() { FILE *fin = fopen("calfflac.in", "r"); FILE *fout = fopen("calfflac.out", "w"); char c, txt[SZ]; int i, j, k, n, txt_len; int low, high, pal_len; for(i = 0; (c = fgetc(fin)) != EOF; i++) txt[i] = c; txt_len = i; low = high = pal_len = 0; for(k = 0; k < txt_len - 1; k++) { i = k; j = k + 1; n = has_pal(txt, txt_len, &i, &j);//even if(n > pal_len) { low = i; high = j; pal_len = n; } i = k - 1; j = k + 1; n = has_pal(txt, txt_len, &i, &j);//odd if(n > pal_len) { low = i; high = j; pal_len = n; } } fprintf(fout, "%d/n", pal_len); for(; low < high; low++) fprintf(fout, "%c", txt[low]); fprintf(fout, "%c/n", txt[high]); exit(0); }  

     


    分析的解法基本思路与我的是一样的,不过实现上略有不同,它把输入串保存在两个数组中,一个是原始数组,一个是去掉标点空白的纯文本数组,然后利用后一个数组找最长回文串的长度,最后再在原始数组中输出整个的回文串。。。


    这道题给了我很多教训:

    一,不要过度依赖测试用例,要自己把所有可能的情况尽量想到,每次提交都被打回来的滋味相当不好受,严重打击积极性。。。

    二,构造算法时一定要想到极限情况,并设计可以经受住考验的算法,时间复杂度太高可不是一件小事!!

    三,拓宽思路,自己多想想,不要一遇到问题就找Google,这么急赶着投胎啊?!

     


    最新回复(0)