По Вашему вопросу:
search_string = 'Spam'
d = {1: {1: {'string': 'Spam'}, 2: {'string': 'Spam, Spam'}, 3: {'string': 'Ham'}}}
dict_result = {}
#
for key, value in d.iteritems():
for key1, value1 in value.iteritems():
for key2, value2 in value1.iteritems():
if search_string in str(value2):
dict_result.setdefault(key, {}).update({key1: value2})
print dict_result
Но, если количество вложений не известно, то лучше использовать рекурсию. Писать рекурсию для Вашего примера не буду, но посмотрите повнимательнее на этот код:
search_string = 'Spam'
d = {1: {1: {'string': 'Spam'}, 2: {'string': 'Spam, Spam'}, 3: {'string': 'Ham'}}}
dict_result = {}
#
def find_string(dict_):
for data in dict_.itervalues():
if type(data) is dict:
find_string(data)
else:
print data
#
find_string(d)
Будут вопросы - пишите.
P.S. Все там работает корректно