回答編集履歴

2

コード追加

2021/11/17 15:07

投稿

退会済みユーザー
test CHANGED
@@ -110,7 +110,7 @@
110
110
 
111
111
  result.append(s)
112
112
 
113
- else: # len(s) が MAX_LENGTH をてい、このsを作ったi_frをfront_indexesから削除
113
+ else: # len(s) が MAX_LENGTH をえたので、このsを作ったi_frをfront_indexesから削除
114
114
 
115
115
  front_indexes.pop(0)
116
116
 

1

コード追加

2021/11/17 15:06

投稿

退会済みユーザー
test CHANGED
@@ -47,3 +47,115 @@
47
47
 
48
48
 
49
49
  ```
50
+
51
+
52
+
53
+ ### 追記
54
+
55
+
56
+
57
+ 上記に挙げたコードは、何をやっているかが分かりやすいかもしれませんが、ちょっと芸がない気がしました。それで
58
+
59
+ - one-pass(所与の`body`の最初から最後まで走査するのを一回で済ませること)で、出来ないか?
60
+
61
+ - 無駄を省く何らかの最適化が出来ないか?
62
+
63
+
64
+
65
+ ということで以下のコードになりました。
66
+
67
+
68
+
69
+ ```python3
70
+
71
+ # body = 'ABccABcccDEccccDE'
72
+
73
+ body = 'AB123AB67890DExxDEyyyABzzDE##ABDE@@@@@DE' # 動作確認用
74
+
75
+ front = 'AB'
76
+
77
+ rear = 'DE'
78
+
79
+
80
+
81
+ MIN_LENGTH = 2
82
+
83
+ MAX_LENGTH = 10
84
+
85
+
86
+
87
+ result = [] # 条件に該当した文字列を格納するリスト
88
+
89
+ front_indexes = [] # front文字列の開始位置をappendしつつ、使わなくなったものは先頭からpop(0)で削除していくFIFOリスト
90
+
91
+
92
+
93
+ # body を左から読み、front および rear の出現を処理するループ
94
+
95
+ for i in range(len(body)):
96
+
97
+ if body[i:i+len(front)] == front:
98
+
99
+ front_indexes.append(i)
100
+
101
+ elif body[i:i+len(rear)] == rear:
102
+
103
+ for i_fr in [*front_indexes]:
104
+
105
+ s = body[i_fr + len(front):i] # AB と DE の間にある文字列
106
+
107
+ if len(s) <= MAX_LENGTH:
108
+
109
+ if MIN_LENGTH <= len(s):
110
+
111
+ result.append(s)
112
+
113
+ else: # len(s) が MAX_LENGTH を越えていたら、このsを作ったi_frをfront_indexesから削除
114
+
115
+ front_indexes.pop(0)
116
+
117
+
118
+
119
+
120
+
121
+ print(result)
122
+
123
+ print(front_indexes)
124
+
125
+
126
+
127
+ ```
128
+
129
+ - サンプル ???? [tera: 369789 別案](https://replit.com/@kilesa/tera-369789-Bie-An?v=1)**@replit**
130
+
131
+
132
+
133
+ **出力結果:**
134
+
135
+ > ['123AB67890', '67890', '67890DExx', 'zz', 'zzDE##AB', 'DE@@@@@']
136
+
137
+ [29]
138
+
139
+
140
+
141
+
142
+
143
+ 基本的な流れは以下です。
144
+
145
+
146
+
147
+ - `body` を左端から右端まで読み、`front`文字列が見つかったら、`front_indexes`にその位置を追加します。
148
+
149
+ - `rear`文字列が見つかったら、`front_indexes`に保持している、`front`のインデクスを小さいほうから読み、`front`と`rear`に挟まれている部分文字列を`s` として作ります。
150
+
151
+ - `s` の長さが要件を満たしていれば、該当文字列のリストに追加します。
152
+
153
+ - `s` の長さが要件の最大長を超えていれば、その`s`を作った`front`インデクスは、以後、使われないので、`front_indexes`から削除します。
154
+
155
+
156
+
157
+ 上記の実行例では、`front`文字列の出現箇所は、0, 5, 21, 29 の4箇所ですが、プログラムの実行中、`front_indexes`の長さは最大2までにしかならず、プログラム終了時には最後の出現位置の 29 のみを含むリストになっています。
158
+
159
+
160
+
161
+ ※いちおう良さげに動いてるっぽいですが、どこかバグっていたら、コメントからお知らせください。