|
ありがとうございます。これで試してみます!
▼γ さん:
>最長共通部分列(longest common subsequence)問題という
>比較的良く知られた問題らしいです。
>(文章の差異を表示するDiffコマンドというものも同じアルゴリズムの系列です。)
>
>大昔、こちらの掲示板に投稿したものの一部を修正(表示の一部を削除)したものです。
>参考にしてください。
>
>Sheet1のA列とB列を比較した結果を、
>Sheet2のA列とB列に表示します。(不一致箇所を赤文字かつアンダーラインで表示)
>
>Option Explicit
>
>Dim lcs() As Long
>Dim dic1 As Object
>Dim dic2 As Object
>Dim s1 As String
>Dim s2 As String
>Dim ws1 As Worksheet
>Dim ws2 As Worksheet
>
>Sub main()
> Dim k As Long
>
> Set ws1 = Worksheets("Sheet1")
> Set ws2 = Worksheets("Sheet2")
>
> '書き込み先のシートをクリアー
> ws2.UsedRange.Clear
>
> 'A列とB列の差異を調べて結果をSheet2に表示する
> For k = 1 To ws1.Cells(ws1.Cells.Rows.Count, 1).End(xlUp).Row
> diff ws1.Cells(k, 1), ws1.Cells(k, 2)
> Next
>End Sub
>
>Sub diff(r1 As Range, r2 As Range)
> Dim ar1, ar2
> Dim v
> Dim pos As Long
> Dim kk As Long
>
> Set dic1 = CreateObject("Scripting.Dictionary")
> Set dic2 = CreateObject("Scripting.Dictionary")
>
> ' 二つの文字列のLCSの長さを求める
> get_lcs r1, r2
>
> 'それに対応する最長共通部分列を求める
> get_lcs_string r1.Value, r2.Value
>
> '結果をSheet2に書き込む
> pos = Application.Max(ws2.Cells(ws2.Rows.Count, 1).End(xlUp).Row, _
> ws2.Cells(ws2.Rows.Count, 2).End(xlUp).Row) _
> + 1
> ws2.Cells(pos, 1) = s1
> ws2.Cells(pos, 2) = s2
>
> '最長共通部分列に該当しない文字列に、書式を設定(赤、アンダーライン)
> setColor ws2.Cells(pos, 1), ws2.Cells(pos, 2)
>End Sub
>
>Function get_lcs(r1 As Range, r2 As Range)
> Dim j As Long, k As Long
>
> s1 = r1.Value
> s2 = r2.Value
> ' lcs(j,k) は s1の1からjまでの部分列と
> ' s2の1からkまでの部分列との
> ' LCSの長さを示す
> ReDim lcs(0 To Len(s1), 0 To Len(s2))
> For j = 1 To Len(s1)
> For k = 1 To Len(s2)
> If Mid(s1, j, 1) = Mid(s2, k, 1) Then
> lcs(j, k) = lcs(j - 1, k - 1) + 1
> Else
> lcs(j, k) = WorksheetFunction.Max(lcs(j, k - 1), lcs(j - 1, k))
> End If
> Next
> Next
>End Function
>
>Function get_lcs_string(s1 As String, s2 As String)
> get_lcs_string_sub Len(s1), Len(s2)
>End Function
>
>Function get_lcs_string_sub(j As Long, k As Long)
> If j = 0 Or k = 0 Then Exit Function
> If Mid(s1, j, 1) = Mid(s2, k, 1) Then
> Call get_lcs_string_sub(j - 1, k - 1)
> dic1(j) = Empty 's1 の j番目の文字がLCSを構成
> dic2(k) = Empty 's2 の k番目の文字がLCSを構成
> Else
> If lcs(j - 1, k) >= lcs(j, k - 1) Then
> Call get_lcs_string_sub(j - 1, k)
> Else
> Call get_lcs_string_sub(j, k - 1)
> End If
> End If
>End Function
>
>Function get_partition(s As String, d As Object) As Variant
> Dim key
>
> For Each key In d.keys
> Mid$(s, key, 1) = "_" ' 余り使用されない文字の意
> Next
> get_partition = Split(s, "_")
>End Function
>
>Function setColor(r1 As Range, r2 As Range)
> Dim j As Long, k As Long
>
> '背景色を水色
> r1.Interior.ColorIndex = 34
> r2.Interior.ColorIndex = 34
>
> 'マッチしない文字列の文字色を赤に
> For j = 1 To Len(r1.Value)
> If Not dic1.exists(j) Then
> With r1.Characters(Start:=j, Length:=1).Font
> .Underline = xlUnderlineStyleSingle
> .ColorIndex = 3
> End With
> End If
> Next
>
> For k = 1 To Len(r2.Value)
> If Not dic2.exists(k) Then
> With r2.Characters(Start:=k, Length:=1).Font
> .Underline = xlUnderlineStyleSingle
> .ColorIndex = 3
> End With
> End If
> Next
>End Function
|
|