合計 昨日 今日

文字列探索プログラムの日本語化について

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: せうご
[URL]
Date: 2018年1月10日(水) 17:10
No: 1
(OFFLINE)

 文字列探索プログラムの日本語化について

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <string.h>
char S1[100], S2[100];
//最少値を求める
int min(int a, int b, int c)
{
    return a > b ? (b > c ? c : b) : (a > c ? c : a);
}
int main()
{
    scanf("%s", S1);
    scanf("%s", S2);
    //編集距離計算
    int lenstr1 = strlen(S1) + 1;
    int lenstr2 = strlen(S2) + 1;
    int d[100][100];
    int i1 = 0, i2 = 0, cost = 0;
 
    for (; i1 < lenstr1; i1++) d[i1][0] = i1;
    for (; i2 < lenstr2; i2++) d[0][i2] = i2;
 
    for (i1 = 1; i1 < lenstr1; i1++) {
        for (i2 = 1; i2 < lenstr2; i2++) {
            cost = S1[i1 - 1] == S2[i2 - 1] ? 0 : 1;
            d[i1][i2] = min(d[i1 - 1][i2] + 1, d[i1][i2 - 1] + 1, d[i1 - 1][i2 - 1] + cost);
        }
    }
 
    printf("編集距離は%dです\n", d[lenstr1 - 1][lenstr2 - 1]);
}

このプログラムを日本語対応しようとしているのですが、正確な値が出せません。
例えば、あいうえお、いうえお、という文字列を比較した際、編集距離は1になるはずなのですが
2と表示されてしまいます。
ご教授お願い致します。

Name: かずま
[URL]
Date: 2018年1月10日(水) 18:10
No: 2
(OFFLINE)

 Re: 文字列探索プログラムの日本語化について

wchar_t と locale を使えばよいでしょう、
コード[C]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <wchar.h>   // wcslen     // 変更
#include <locale.h>  // setlocale  // 追加
 
wchar_t S1[100], S2[100];          // 変更
 
int min(int a, int b, int c)
{
    return a > b ? (b > c ? c : b) : (a > c ? c : a);
}
 
int main()
{
    setlocale(LC_CTYPE, "");       // 追加
    scanf("%ls", S1);              // 変更
    scanf("%ls", S2);              // 変更
    //編集距離計算
    int lenstr1 = wcslen(S1) + 1;
    int lenstr2 = wcslen(S2) + 1;
    int d[100][100];
    int i1 = 0, i2 = 0, cost = 0;
 
    for (; i1 < lenstr1; i1++) d[i1][0] = i1;
    for (; i2 < lenstr2; i2++) d[0][i2] = i2;
 
    for (i1 = 1; i1 < lenstr1; i1++) {
        for (i2 = 1; i2 < lenstr2; i2++) {
            cost = S1[i1 - 1] == S2[i2 - 1] ? 0 : 1;
            d[i1][i2] = min(d[i1 - 1][i2] + 1, d[i1][i2 - 1] + 1, d[i1 - 1][i2 - 1] + cost);
        }
    }
 
    printf("編集距離は%dです\n", d[lenstr1 - 1][lenstr2 - 1]);
}

Name: せうご
[URL]
Date: 2018年1月10日(水) 20:43
No: 3
(OFFLINE)

 Re: 文字列探索プログラムの日本語化について

ありがとうございます。
ご指摘のようにwchar_tを使った方法は検討したのですが、エラーこそ起きないものの、正しい結果が表示されませんでした。
例えばきりぎりすときらぎすを比べた際、結果は2となるはずが1となってしまいます。
計算方法そのものに間違いがあるのでしょうか。
ご検討お願いします。

Name: かずま
[URL]
Date: 2018年1月10日(水) 21:42
No: 4
(OFFLINE)

 Re: 文字列探索プログラムの日本語化について

OS とコンパイラは何ですか?

Linux の gcc では、問題なく編集距離は 2 になりました。

Windows の VC++ の scanf の "%ls" には、バグがあるようです。
次のように wscanf を使用すると、このバグを回避できるようです。
コード[C]: 全て選択
1
2
    wscanf(L"%ls", S1);
    wscanf(L"%ls", S2);

Name: かずま
[URL]
Date: 2018年1月13日(土) 15:44
No: 5
(OFFLINE)

 Re: 文字列探索プログラムの日本語化について

まだ解決にならないのでしょうか?

int d[100][100]; ですが、表を上から順番に作っていくので、
ある行と、その次の行の二つの行だけでできます。
コード[C]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>   // printf
#include <wchar.h>   // wcslen, wscanf
#include <locale.h>  // setlocale
 
int min(int a, int b, int c)
{
    return a < b ? (a < c ? a : c) : (b < c ? b : c);
}
 
int main(void)
{
    setlocale(LC_CTYPE, "");
 
    wchar_t s1[100], s2[100];
    wscanf(L"%ls", s1), wscanf(L"%ls", s2);
    int n1 = wcslen(s1), n2 = wcslen(s2);
    int d[2][100], *a = d[0], *b = d[1], *t;
 
    for (int j = 0; j <= n2; j++) a[j] = j;
 
    for (int i = 0; i < n1; i++) {
        b[0] = i + 1;
        for (int j = 0; j < n2; j++)
            b[j+1] = min(a[j+1] + 1, b[j] + 1, a[j] + (s1[i] != s2[j]));
        t = a, a = b, b = t;
    }
 
    printf("編集距離は %d です\n", a[n2]);
}


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[12人]