15章 Suffix配列を実装してみた
そろそろ終盤!
15章の問題に入る前にこの章の主題(?)を実装した.
文字列内の最長部分一致を見つける.
このアルゴリズムをSuffix配列と云うらしい.
qsortは不便だということを再確認(仕方ないけど).
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; void print_words(char ** ws, int N){ for(int j=0; j<N; ++j){ cout << "["<<j<<"]" << ws[j] << endl; } } int strcmp2(void const * const *x, void const * const *y){ return strcmp((const char*)*x, (const char*)*y); } int common_length(char * sa, char * sb){ int i; for(i=0; sa[i]!='\0'&&sb[i]!='\0'; i++){ if(sa[i]!=sb[i]){ break; } } return i; } void find_common_word(FILE * fp, int N){ char * buff = new char[N]; char ** suffix = new char*[N]; char c; int i; for(i=0; (c=fgetc(fp))!=EOF && i<N-1; i++){ // #bug buff[i] = c; suffix[i] = &buff[i]; } buff[i]='\0'; suffix[i] = &buff[i]; print_words(suffix, i); typedef int (*cmp_func)(const void*,const void*); qsort(suffix, i, sizeof(char*), (cmp_func)&strcmp2); print_words(suffix, i); int maxlen=0; int maxindex=-1; for(int k=0; k<i-1; k++){ int len=common_length(suffix[k], suffix[k+1]); cout << suffix[k] << ":" << suffix[k+1] << " => " << len << endl; if(len>maxlen){ maxlen=len; maxindex=k; } } cout << "maxlen=" << maxlen << endl; cout << "maxindex=" << maxindex << endl; cout << "string=[" << endl; cout << "\t[" << suffix[maxindex] << "]" << endl; cout << "\t[" << suffix[maxindex+1] << "]" << endl; delete buff; delete suffix; } int main(){ const int N = 100; FILE * fp=fopen("tmp.hpp", "r"); if(!fp){ goto ERROR_EXIT; } find_common_word(fp, N); ERROR_EXIT: fclose(fp); return (0); }
最初,コード中#bugのところの条件を間違えて
char buff[100]; // 始めはmain関数のスタック上に置いてた for(i=0; (c=fgetc(fp))!=EOF && i<N ; i++){ // bug :( for(i=0; (c=fgetc(fp))!=EOF && i<N-1; i++){ // ok :)
こんな感じに間違えてしまい,これをVC2008で実行すると
returnでmainから抜けるときに*1エラー吐いて落ちた….
これが入り組んだコードで発生したら…デバッグする自身がないorz
*1:多分スタック上の配列をdeleteしてる時