使用模式生成合理的字符串

时间:2011-07-26 11:08:54

标签: string design-patterns pattern-matching

我有一个字符串表(大约100,000),格式如下:

pattern , string

e.g。 -

*l*ph*nt , elephant
c*mp*t*r , computer
s*v* , save
s*nn] , sunny
]*rr] , worry

为了简化,假设*表示元音,辅音保持不变,]表示'y'或'w'(例如,半元音/圆形 - 音韵中的元音)。

给定一种模式,生成可能的合理字符串的最佳方法是什么?一个合理的字符串被定义为一个字符串,它的每个连续的两个字母的子串都没有在模式中指定,在数据集中。

e.g。 -

h * ll * - >你好,你好,霍拉......

'hallo'是明智的,因为'ha','al','lo'可以在数据集中看到,如'have','also','low'。不考虑两个字母'll',因为它是在模式中指定的。

有哪些简单有效的方法? 是否有任何库/框架来实现这一目标?

我没有特定的语言,但更喜欢在这个程序中使用java。

2 个答案:

答案 0 :(得分:0)

由于双字母子串的可能性不大,您可以浏览数据集并生成一个包含每个双字母子字符串计数的表,因此该表将如下所示:

ee    1024 times
su    567 times
...
xy    45 times
xz    0 times

该表格很小,因为您只能存储约26 * 26 = 676个值。

您只需对数据集执行一次此操作(如果数据集是动态的,则每次更改时都必须更新表),并且可以使用该表来评估可能的字符串。例如,为您的示例添加'ha','al'和'lo'的值,以获得字符串'hallo'的“得分”。之后,选择得分最高的字符串。

请注意,可以通过检查更长的子串f.e来改进评分。三个字母,但这也会导致更大的表格。

答案 1 :(得分:0)

这特别适合Python itertools 设置重新操作:

import re
import itertools

VOWELS      = 'aeiou'
SEMI_VOWELS = 'wy'
DATASET     = '/usr/share/dict/words'
SENSIBLES   = set()

def digraphs(word, digraph=r'..'):
    '''
    >>> digraphs('bar')
    set(['ar', 'ba'])
    '''
    base = re.findall(digraph, word)
    base.extend(re.findall(digraph, word[1:]))
    return set(base)

def expand(pattern, wildcard, elements):
    '''
    >>> expand('h?', '?', 'aeiou')
    ['ha', 'he', 'hi', 'ho', 'hu']
    '''
    tokens = re.split(re.escape(wildcard), pattern)
    results = set()
    for perm in itertools.permutations(elements, len(tokens)):
        results.add(''.join([l for p in zip(tokens, perm) for l in p][:-1]))
    return sorted(results)

def enum(pattern):
    not_sensible = digraphs(pattern, r'[^*\]]{2}')
    for p in expand(pattern, '*', VOWELS):
        for q in expand(p, ']', SEMI_VOWELS):
            if (digraphs(q) - not_sensible).issubset(SENSIBLES):
                print q

## Init the data-set (may be long...)
## you may want to pre-compute this
## and adapt it to your data-set.
for word in open(DATASET, 'r').readlines():
    for digraph in digraphs(word.rstrip()):
        SENSIBLES.add(digraph)

enum('*l*ph*nt')
enum('s*nn]')
enum('h*ll*')