Во первых ==True здесь совершенно лишнее, contains вернет массив длинной ff['B'], где True, будет означать берем данную строку, ок он не выдаст ошибку, но он тут абсолютно лишний и ничего не делает.
Во вторых, обычно str.contains обычно используют вместе с регуляркой. Предоставляют выражения также используют flags для установки различных параметров, например осуществить поиск не чувствительным к регистру, для примера.
import re
searchstr=(
ff.loc[ff['B']
.str.contains(r'строка',regex=True,flags=re.IGNORECASE),['А','B']
]
)
Выберет подсет датафрейма ff (колонки 'A' и 'B'), где в 'В' содержится 'строка'.