Similar documents
02: 変数と標準入出力

Microsoft Word - 3new.doc

データ構造

Microsoft PowerPoint - 5Chap15.ppt

02: 変数と標準入出力

02: 変数と標準入出力

Prog1_10th

文字列探索

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

データ構造

今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

文字列 2 前回の授業ではコンピュータ内部での文字の取り扱い 文字型の変数 文字型変数への代入方法などを学習した 今回は 前回に引き続き 文字処理を学習する 内容は 標準入出力 ( キーボード ディスプレイ ) での文字処理 文字のファイル処理 文字を取り扱うライブラリ関数である 標準入出力 Lin

講習No.9

Microsoft PowerPoint - kougi7.ppt

Microsoft Word - no103.docx

02: 変数と標準入出力

PowerPoint プレゼンテーション

書式に示すように表示したい文字列をダブルクォーテーション (") の間に書けば良い ダブルクォーテーションで囲まれた文字列は 文字列リテラル と呼ばれる プログラム中では以下のように用いる プログラム例 1 printf(" 情報処理基礎 "); printf("c 言語の練習 "); printf

ポインタ変数

ポインタ変数

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdio.h> #define InFile "data.txt" #define OutFile "sorted.txt" #def

Microsoft PowerPoint - 11.pptx

Microsoft Word - no11.docx

02: 変数と標準入出力

ポインタ変数

1. 入力した文字列を得る 1.1. 関数 scanf() を使う まずは関数 scanf() を使ったプログラムを作ってみましょう 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: #include<stdio.h> #define SIZE 128 main(

Microsoft Word - no202.docx

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

memo

プログラミング実習I

02: 変数と標準入出力

PowerPoint プレゼンテーション

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

02: 変数と標準入出力

02: 変数と標準入出力

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

Report#2.docx

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

ポインタ変数

02: 変数と標準入出力

Taro-ファイル処理(公開版).jtd

プログラミング実習I

< F2D837C E95CF CF68A4A94C5816A2E6A>

kiso2-03.key

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

PowerPoint プレゼンテーション

Microsoft PowerPoint - 計算機言語 第7回.ppt

情報処理Ⅰ

Taro-リストⅠ(公開版).jtd

PowerPoint プレゼンテーション

Taro-ポインタ変数Ⅰ(公開版).j

PowerPoint プレゼンテーション

演算増幅器

Microsoft Word - no02.doc

デジタル表現論・第6回

第1回 プログラミング演習3 センサーアプリケーション

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

Prog1_2nd

Microsoft PowerPoint - lec10.ppt

PowerPoint プレゼンテーション

FORTRAN( と C) によるプログラミング 5 ファイル入出力 ここではファイルからデータを読みこんだり ファイルにデータを書き出したりするプログラムを作成してみます はじめに テキスト形式で書かれたデータファイルに書かれているデータを読みこんで配列に代入し 標準出力に書き出すプログラムを作り

memo

Prog1_6th

PowerPoint プレゼンテーション

program7app.ppt

今回のプログラミングの課題 ( 前回の課題で取り上げた )data.txt の要素をソートして sorted.txt というファイルに書出す ソート (sort) とは : 数の場合 小さいものから大きなもの ( 昇順 ) もしくは 大きなものから小さなもの ( 降順 ) になるよう 並び替えること

Report#2.docx

目次

kiso2-09.key

講習No.8

memo

C プログラミング 1( 再 ) 第 4 回 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ 1

Microsoft PowerPoint - algo ppt [互換モード]

PowerPoint プレゼンテーション

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

講習No.1

Microsoft PowerPoint ppt

PowerPoint プレゼンテーション

第2回

Prog1_15th

CプログラミングI

memo

文字列操作と正規表現

02: 変数と標準入出力

基礎プログラミング2015

ポインタ変数

3,, となって欲しいのだが 実際の出力結果を確認すると両方の配列とも 10, 2, 3,, となってしまっている この結果は代入後の配列 a と b は同じものになっていることを示している つまり 代入演算子 = によるの代入は全要素のコピーではなく 先をコピーする ため 代入後の a と b は

Microsoft PowerPoint ppt

PowerPoint Presentation

memo

情報処理演習 B8クラス

02: 変数と標準入出力

プログラミング基礎

02: 変数と標準入出力

ソフトウェア基礎 Ⅰ Report#2 提出日 : 2009 年 8 月 11 日 所属 : 工学部情報工学科 学籍番号 : K 氏名 : 當銘孔太

Transcription:

文字列処理 ( 教科書 p.301p.332) 今回は 言語の文字列処理について復習し, 文字列の探索手法について学びます. 文字列とはプログラム上での文字の並びを表すのが文字列です. これは中身が空であっても同様に呼ばれます. 言語では "STRING" のように文字の並びを二重引用符 " で囲んだものを文字列リテラルと呼びます. SII コードの場合, 割り当てられる数値は図 1 のようになっています. 文字列リテラル "STRING" S T R I N G \0 各文字は記憶域上に連続的に配置され 末尾にはナル文字が入る 0 1 0 1 0 0 1 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 図 1 文字列リテラル 文字 'S' 文字 'T' 文字 'R' 文字 'I' 文字 'N' 文字 'G' ナル文字 '\0' 各文字はメモリ上に連続して配置され, 文字に対応する数値データによって管理されます. 文字列リテラルには終端を示すためのナル文字が自動的に付加されます. ナル文字は文字コードによらず, 全てのビットが 0 です. 以下の宣言では文字列リテラルによって, ポインタ pt を初期化しています. この場合, 文字列リテラル "1234" がメモリ上に確保されます. char *pt = "1234"; ポインタ 0 1 2 3 4 1 2 3 4 \0 文字列リテラル pt は文字列リテラルの先頭文字 '1' を指す 図 2 ポインタと文字列リテラル 言語では文字列リテラルは定数として扱われ, 文字を再変更する際の動作は保証されていません. 文字列を変更するならば, char st[5] = "1234"; のように配列に文字列を確保した上で行います. 文字列の長さ配列を用いた文字列を利用することを考えます. 文字列の最後には基本的にはナル文字が入っており, 文字列の長さを求める場合, 配列の先頭から始めて, ナル文字を線形探索していけばよいです. その際, ナル文字が見つかった添字が文字列の長さと一致します. ナル文字を線形探索する S T R I N G \0 図 3 文字列と長さ 文字列から文字を探索文字列からナル文字ではなく, 任意の文字を探索する手続きを考えます. 例として文字列 "SURROUN" から文字 'R' を探索すると, 図 4 のように, 配列の先頭から線形探索を行うことになります. 文字 'R' を線形探索する S U R R O U N \0 図 4 文字の探索 1

文字列の比較 言語では二つの文字列を比較するため, 標準ライブラリの string.h において,strcmp 関数と strncmp 関数が提供されています. strcmp 関数この関数の仕様を以下に示す. ヘッダ #include <string.h> 形式 int strcmp(const char *s1, const char *s2); 解説 s1 が指す文字列と s2 が指す文字列の大小関係 ( 先頭から順に 1 文字ずつ比較していき, 異なる文字が出現したときに, それらの文字の対に成立する大小関係とする ) の比較を行う. 返却値等しければ 0,s1 が s2 より大きければ正の整数値,s1 が s2 より小さければ負の整数値を返す. strncmp 関数この関数の仕様を以下に示します. ヘッダ #include <string.h> 形式 int strncmp(const char *s1, const char *s2, size_t n); 解説 s1 が指す文字の配列と s2 が指す文字の配列の先頭 n 文字までの大小関係 ( 先頭から順に 1 文字ずつ比較していき, 異なる文字が出現したときに, それらの文字の対に成立する大小関係とする ) の比較を行う. 返却値等しければ 0,s1 が s2 より大きければ正の整数値,s1 が s2 より小さければ負の整数値を返す. 文字列探索 ( 文字列から文字列を探索 ) 文字列探索とはある文字列の中に特定の文字列が含まれているかどうかを探索し, 位置を特定する処理のことをいいます. たとえば, 文字列 "STRING" や "KING" から文字列 "IN" を探す処理です."IN" のように探し出そうとする文字列をパターンと呼び, 探索する側の文字列をテキストと呼びます. ここでは以下の手法について学んでいきます. 力まかせ法 ( 単純法 ) KMP 法 oyermoore 法 力まかせ法 ( 単純法 0 1 ) 2 3 4 5 6 力まかせ法はテキストの探索開始位置を E 1 つずつ後ろにずらしていき, パターンとの間で E 1 文字ずつ比較していきます. 比較の途中で一致しない場合にはその後の比較は行いません. 以下にテキスト "EFGH" からパターン "" を探索する手続きを示します. パターンの 3 文字目が一致しない パターンの 3 文字目が一致しない E E パターンの3 1 文字目が一致しない パターンの 1 文字目が一致しない E E パターンのパターンの全文字が一致 1 文字目が一致しない 7 8図 59 力まかせ法の概略 E パターンの全文字が一致 2 パターンの全文字が一致

図 5 ではテキストの 1 文字目から比較を行い, パターンの 3 文字目が一致しません. ではテキストの 2 文字目から比較を行い, パターンの 1 文字目が一致しません. ではテキストの 3 文字目から比較を行い, 全ての文字が一致して探索が成功します. KMP 法力まかせ法では文字が一致しない場合, パターンを移動してパターンの先頭から比較を行うことになるため, それまでの照合結果が捨てられてしまいます. それまでの照合結果を有効に利用しようとして考案されたのが KMP 法 (KnuthMorrisPratt 法 ) です. テキスト "ZXEF" からパターン "" を探索するものとします.KMP 法ではまず, テキストとパターンの最初の文字から順に照合していきます. テキストの最初の文字 'Z' はパターンの最初の文字 '' と一致しません. Z X E F 次にパターンを 1 文字ずらし, 再びパターンの先頭から順に照合を行っていくと, パターンの "" まで一致した後, 最後の文字 '' が不一致となります. Z X E F この場合, テキストとパターンの が付いている部分でで示した "" が一致していることに着目し, この部分を照合済みとみなすと, テキスト側の文字 'X' 以降の部分がパターンの "" と一致するかを調べればよいことになります. したがって, 以下に示すようにパターンを 3 文字ずらし,3 文字目の '' から照合を再開することができます. Z X E F このように,KMP 法はテキストとパターン中の重なっている部分をうまく見つけ出して, 照合し直す位置を求め, なるべくパターンの移動を大きくしようとするアルゴリズムです. 実際に利用する場合には, パターン移動の際の何文字目から照合を再開するかについて, 事前に表を作成しておき, 効率を上げることになります. 表を作成するためには, パターン内の重複した文字の並びを見つけなければなりません. パターンの 1 文字目が不一致の場合はパターンを 1 文字ずらして, 先頭文字から照合を再開すればよいです.2 文字目以降については以下のように行います. まず, パターン "" どうしを 1 文字ずらして重ね合わせてみます. 下の図で, 白地で示した配列の部分に重なりは無いので, パターン移動時に先頭から照合をしなくてはならないことが分かります. そこで,2 文字目の '' の再開値を 0 とします. 0 さらに, パターンを 1 文字ずらします. ここでも文字は照合しないので,3 文字目の '' の再開値を 0 とします. 3

0 0 さらに, パターンを 1 文字ずらすと,"" が照合します. そこで, これら二つの文字の再開値を 1 および 2 とします. 0 0 1 2 次は, パターンを 2 文字ずらして比較を行います. 結果, 文字は一致しません. したがって, パターンの最後の文字 '' の再開値を 0 とします. 0 0 1 2 0 KMP 法の特徴はテキストを走査するカーソルが前進するだけになることです. これは力まかせ法には無い特徴です. しかし, このアルゴリズムは比較的複雑ですが, 次に解説する oyermoore 法と同等以下の性能しか発揮できないため, 現実のプログラムで利用されることはあまりありません. oyermoore 法理論的にも実践的にも KMP 法より優れているのが M 法 (oyermoore 法 ) です. 力まかせ法や KMP 法とは異なり, 照合をパターンの末尾文字から始めて先頭側へと進めていくという特徴があります. 一致しない文字を見つけた場合には事前に用意した表に基づいて, その文字に応じたパターンの移動量を決定します. テキスト "XEZ" からパターン "" を探索する例で, このアルゴリズムについて考えます. 探索開始時は, 以下の図 のようにテキストとパターンの先頭文字を重ね, パターンの末尾文字 '' から照合します. 照合するテキストの文字は 'X' ですが, この 'X' はパターンに存在しない文字です. そのため, 図 ~(d) のように 1~3 文字文移動しても一致しないことが分かります. 11 12 13 14 15 X E Z 不一致 1 文字進めても不一致 2 文字進めても不一致 (d) 3 文字進めても不一致 このように, パターンに含まれない文字をテキスト中に発見した場合には, そこまでの文字は全てスキップできることが分かります. そこで, 次の照合の開始位置はパターンを一気に 4 文字後ろに移動します. 11 12 13 14 15 X E Z 一致 パターンの末尾文字 '' をテキストと比較すると, 今度は一致しているので, 次は一つ前の文字へ戻ります. 4

11 12 13 14 15 X E Z 不一致 1 文字進めても不一致 2 文字進めても不一致 パターンの文字は '' であり, テキストの 'Z' とは一致しません. この場合, 図, のようにパターンを 1,2 文字移動しても, 文字 'Z' とは一致することはありません. よって, 次の照合の開始位置はパターンを一気に 3 文字後ろに移動することができます. 11 12 13 14 15 X E Z 不一致 1 文字進めればよい 2 文字進めても不一致 (d) 3 文字進めては駄目 図 に示すように, テキスト側の文字 '' はパターン末尾の文字 '' と一致しません. しかし, このテキストの文字 '' はパターン中の 1 文字目と 3 文字目の 2 箇所に含まれています. そこで, 図 に示すように後ろ側の '' が重なるようにパターンを 1 文字だけ移動します. この時, パターンの先頭側の '' に重ねようとして一気に 3 文字移動しては上手くいきません. パターンを移動すると次の図のようになります. 末尾側から順に文字を比較すると, すべて一致するので, これで探索は成功です. 11 12 13 14 15 X E Z 全ての文字が一致 探索成功 このアルゴリズムを利用するためには, 各文字に出会ったときに, 現在照合中の文字を何文字分ずらすかを事前に表にしておく必要があります. ここに示した例では次のスキップテーブルのようになります. E I J K L M 1 2 4 4 4 4 4 4 4 4 4 4 4 N 4 4 O P Q R S T U V W X Y Z 4 4 4 4 4 4 4 4 4 4 4 この表にない文字 ( 小文字や数字など ) についての移動量はすべて 4 スキップテーブル 課題 4 1. 力任せ法,KMP 法,oyerMoore 法についてまとめてください. 2. 力任せ法,KMP 法,oyerMoore 法の速度を測定します. その上で考察を行って下さい. 速度の測定 5

については clock() は 1ms 程度の精度となっていますので, これ以上の測定時間となるよう, 十分なサイズのテキストを用意して下さい. 繰り返し処理を併用しても良いです. 参考 : 時間の測定プログラム #include <stdio.h> #include <time.h> /* clock_t,loks_per_se を使うために必要 */ int main(void) { clock_t begin, end; begin = clock(); /* 開始時間を記録 */ func(); /* 測定したいプログラムを書く */ end = clock(); /* 終了時間を記録 */ printf(" 測定時間 %f 秒 \n",(float)(endbegin)/loks_per_se); } return 0; clock_t clock(void) clock はプログラム実行開始から経過したプロセッサ時間 ( エラー時は 1 ) を返します. clock()/loks_per_se は秒で表された時間です. 使用するには time.h が必要です. 6