有一个类似的字符串
dxabcabcyyyydxycxcxz
我希望将其合并到
中dxabcydxycxz
其他例子: ddxddx - > dxdx,abbab - > abab。
规则是:
if (adjacent and same): merge
# Such as 'abc',they are same and , so I will delete one of them .
# Although 'dx' is same as 'dx',they are nonadjacent,so I do not delete any of them
# If one character has been deleted, we don't delete any sub-string include it
我是在python的代码中完成的,但是在长字符串中它的速度很慢。
# original string
mystr = "dxabcabcyyyydxycxcxz"
str_len = len(mystr)
vis = [1] *str_len #Use a list to mark which char is deleted
# enumerate the size of sub-str
for i in range(1,str_len):
# enumerate the begin of the sub-str
for j in range(0, str_len):
offset = 2 #the size of sub-str + 1
current_sub_str = mystr[j:j+i]
s_begin = j+i*(offset-1)
s_end = j+(i*offset)
# delete all of the same char
while((j+(i*offset) <= str_len) and current_sub_str == mystr[s_begin:s_end]
and 0 not in vis[s_begin:s_end] and 0 not in vis[j:j+i]):
vis[s_begin:s_end] = [0] * (s_end - s_begin) #if I deleted it ,mark it as 0
offset += 1
s_begin = j + i * (offset - 1)
s_end = j + (i * offset)
res = []
for i in range(0,str_len):
if(vis[i]!=0): res.append(mystr[i])
print "".join(res)
有没有更快的方法来解决它?
2017年4月29日更新
抱歉,这似乎是一个XY问题。另一方面,它可能不是。 有内容
我正在编写一个网络蜘蛛编码,并且有很多标记路径就像那些
ul/li/a
ul/li/div/div/div/a/span
ul/li/div/div/div/a/span
ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
ul/li/ul/li/a
如您所见,有一些标记路径&#39;我也是这样做的,所以我想把它们折叠起来,发现其他任何标签路径都有相同的结构。 折叠后,我得到了标记路径&#39;像这样。
ul/li/a
ul/li/div/div/div/a/span
ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
这只是我的想法,我不知道这样做是否合适。(尝试之后,我选择了另一种方式来做。
然而,有一个有趣的问题,如ACM问题。
所以我简化了一个标记路径&#39;对于一个角色并寻求帮助。因为我自己没有快速行动。 实际上,这个问题有许多我不介意的角落,并感谢大家帮助我完成它。
谢谢大家。
答案 0 :(得分:15)
看到正则表达的力量:
>>> import re
>>> re.sub(r"(.+?)\1+", r"\1", "dxabcabcyyyydxycxcxz")
'dxabcydxycxz'
>>> re.sub(r"(.+?)\1+", r"\1", "ddxddx")
'dxdx'
>>> re.sub(r"(.+?)\1+", r"\1", "abbab")
'abab'
这会查找包含1个或多个任意字符(.+?)
的序列(作为非贪婪匹配,以便首先尝试更短的序列),然后重复匹配序列{{1}的1次或多次重复},并将其全部替换为匹配的序列\1+
。
答案 1 :(得分:0)
这可以是一个开始:
for i in range(len(string)):
for j in range(i + 1, len(string)):
while string[i:j] == string[j:j + j - i]:
string = string[:j] + string[j + j - i:]
提供的示例的结果:
abbab -> abab
ddxddx -> dxdx
abcabcabc -> abc
dxabcabcyyyydxycxcxz -> dxabcydxycxz
答案 2 :(得分:0)
这是一个很好的问题/系列回复!
这是使用生成器和字符串切片的实现:
import math
def dedupe(string, step=1):
index = 0
prior = ''
while index < len(string):
letter = string[index]
window = index + step
comparison = string[index:window]
if comparison != prior:
yield letter
prior += letter
index += 1
else:
index += step
if len(prior) > (step):
prior = prior[1:] # remove first character
def collapse(string):
step = 1
while step < math.sqrt(len(string)):
generator = dedupe(string, step=step)
string = ''.join(generator)
step +=1
return string
编辑:更改了步骤搜索以使用长度的平方根来改善搜索时间:
%timeit collapse('dxabcabcyyyydxycxcxz')
10000循环,最佳3:每循环24.7μs%timeit collapse(randomword(100)
1000循环,最佳3:每循环384μs%timeit collapse("a" * 100)
10000个循环,最佳3:每循环27.1μs%timeit collapse(randomword(50) * 2)
1000循环,最佳3:每循环382μs答案 3 :(得分:0)
一行:
def remove_repeats(iterable):
return [e for (i, e) in enumerate(iterable) if i == 0 or e != iterable[i - 1]]
它适用于任何可迭代数据,返回列表。
>>> print remove_repeats("aaabbc")
['a', 'b', 'c']
>>> s = '''
... ul/li/a
... ul/li/div/div/div/a/span
... ul/li/div/div/div/a/span
... ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... ul/li/ul/li/a
... '''
>>> print remove_repeats(s.split())
['ul/li/a', 'ul/li/div/div/div/a/span', 'ul/li/a', 'ul/li/ul/li/a', 'ul/li/a', '
ul/li/ul/li/a', 'ul/li/a', 'ul/li/ul/li/a']
如果您需要字符串,请加入:
>>> print "".join(remove_repeats('111222333'))
123
>>> print "\n".join(remove_repeats(s.split()))
ul/li/a
ul/li/div/div/div/a/span
ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
ul/li/a
ul/li/ul/li/a
答案 4 :(得分:0)
from collections import OrderedDict
mystr = "dxabcabcyyyydxycxcxz"
index=0;indexs = [];count = OrderedDict()
while count!=None:
count = {}
for index in range(0,len(mystr)):
flag = True
for index1 in range(0,index+1)[::-1]:
if(mystr.startswith(mystr[index1:index+1], index+1)):
if count.get(str(index1),0)<(index+1-index1):
count.update({str(index1) : index+1-index1})
for key in count:
mystr = mystr[:int(key)]+mystr[int(key)+count[key]:]
if count=={}:
count=None
print "Answer:", mystr
答案 5 :(得分:0)
一种线性方法
import itertools
_str = 'dxabcabcyyyydxycxcxz'
print ''.join(ch for ch, _ in itertools.groupby(_str))
结果:
dxabcabcyyyydxycxcxz - &gt; dxabcabcydxycxcxz