求:高效的字符串比较,要求只有一个字符差异。

DreamTiger 2011-08-11 11:48:04
需求:判断两个字符串是否有且仅有一个字符的差异,下面是我的程序,但感觉应该还可以提高很多,特征求快速算法,多谢。

public static bool IsMutationOne(string seq1, string seq2)
{
if (seq1.Length != seq2.Length)
{
return false;
}

for (int i = 0; i < seq1.Length; i++)
{
if (seq1[i] != seq2[i])
{
return seq1.Substring(i + 1).Equals(seq2.Substring(i + 1));
}
}

return false;
}

...全文
311 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
qldsrx 2011-08-12
  • 打赏
  • 举报
回复
你要能用unsafe代码,下面这段应该是执行最快的,你自己试试。

/// <summary>
/// 判断两个字符串是否有且仅有一个字符的差异
/// </summary>
public static unsafe bool IsMutationOne(string seq1, string seq2)
{
int len = seq1.Length;
if (len != seq2.Length)
{
return false;
}

bool isfind = false;
fixed (char* pseq1 = seq1)
{
fixed (char* pseq2 = seq2)
{
char* p1 = pseq1;
char* p2 = pseq2;
for (int i = 0; i < len; i++)
{
if (*p1 != *p2)
{
if (isfind)
return false;
else
isfind = true;
}
p1++; p2++;
}
}
}
return isfind;
}
showjim 2011-08-12
  • 打赏
  • 举报
回复
写了个Hash的供参考,楼主也可以改成排序+二分查找的
    public class stringCompare
{
private HashSet<string> Values;
private char NullChar;
public stringCompare(string[] values, char nullChar)
{
NullChar = nullChar;
Values = new HashSet<string>();
foreach (string oldValue in values)
{
foreach (string value in split(oldValue)) Values.Add(value);
}
}
private unsafe string[] split(string value)
{
int length = value.Length;
string[] values = new string[length];
fixed (char* chars = value.ToCharArray())
{
int index = length;
do
{
chars[--index] = NullChar;
values[index] = new string(chars, 0, length);
chars[index] = value[index];
}
while (index > 0);
}
return values;
}
public bool isValue(string oldValue)
{
foreach (string value in split(oldValue))
{
if (Values.Contains(value)) return true;
}
return false;
}
}
showjim 2011-08-12
  • 打赏
  • 举报
回复
如果楼主有500M内存可用,可以考虑Hash可排序。
如果建hash,单次查询的代价是o(20)=O(1)
如果排序,单次查询的代价是o(20*log(n))=O(log(n))
至于实际效率哪个好,需要楼主自己测试了。

这种方案都需要将一个字符串拆成长度个字符串。如abcde要拆成?bcde,a?cde,ab?de,abc?e,abcd?。
?表示实际字符串中不可能出现的替代字符。
查询的时候也是要拆成这么多个字符串分别查询。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 q107770540 的回复:]

C# code

public static bool IsMutationOne(string seq1, string seq2)
{
return seq1.ToCharArray().Except(seq2.ToCharArray()).Count()==1;
}
[/Quote]

顺序有影响。另外,用Except速度会更快么?
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qldsrx 的回复:]

把你的代码改了下,效率可以提高很多(如果启用指针,速度更快,不过字符串要很长的时候才会有感觉)。
C# code

public static bool IsMutationOne(string seq1, string seq2)
{
if (seq1.Length != seq2.Length)
{
……
[/Quote]

嗯。这是我最早的版本,后来在猜想是否用equals会更快,毕竟只要有一个不一样就直接返回了。而这个代码需要比较完所有字符才做判断。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 qldsrx 的回复:]

你都在遍历string了,何必还用自带的Equals来比较,如果你打算用Equals来比较,最开始就该用自带的,而不是自己写,String有个现成的函数可以满足你的要求,要不要用就随便你了。

String.CompareOrdinal
返回差异的字符个数,为1就是你要的结果,速度应该不会太慢,反正实际需求足够。
[/Quote]

这个有点问题哦。String.CompareOrdinal返回值不是差异的字符个数。
至于代码本身,估计得考虑用unsafe代码来进行了。
q107770540 2011-08-11
  • 打赏
  • 举报
回复

public static bool IsMutationOne(string seq1, string seq2)
{
return seq1.ToCharArray().Except(seq2.ToCharArray()).Count()==1;
}
qldsrx 2011-08-11
  • 打赏
  • 举报
回复
把你的代码改了下,效率可以提高很多(如果启用指针,速度更快,不过字符串要很长的时候才会有感觉)。

public static bool IsMutationOne(string seq1, string seq2)
{
if (seq1.Length != seq2.Length)
{
return false;
}

int num = 0;
for (int i = 0; i < seq1.Length; i++)
{
if (seq1[i] != seq2[i])
{
num++;
}
}
if (num == 1) return true;
else return false;
}
q107770540 2011-08-11
  • 打赏
  • 举报
回复
顺序也有限制?
你可以举个例子
无常名 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 qldsrx 的回复:]
你都在遍历string了,何必还用自带的Equals来比较,如果你打算用Equals来比较,最开始就该用自带的,而不是自己写,String有个现成的函数可以满足你的要求,要不要用就随便你了。

String.CompareOrdinal
返回差异的字符个数,为1就是你要的结果,速度应该不会太慢,反正实际需求足够。
[/Quote]

+1
qldsrx 2011-08-11
  • 打赏
  • 举报
回复
你都在遍历string了,何必还用自带的Equals来比较,如果你打算用Equals来比较,最开始就该用自带的,而不是自己写,String有个现成的函数可以满足你的要求,要不要用就随便你了。

String.CompareOrdinal
返回差异的字符个数,为1就是你要的结果,速度应该不会太慢,反正实际需求足够。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 lost_painting 的回复:]

"这个函数用于大概数百万个6-20长度的字符串集合,查询其中每个字符串在另外一个数百万个6-20长度的字符串集合中是否存在只有一个位置不一样的字符串"

没看出来. --> "考虑到实际需求,只考虑等长字符串的比较。"
[/Quote]

呵呵。我说的是实际项目的需求。或者,应该描述成“寻找长度相等、有且只有一个位置不一样的字符串”就完整了。
鸭梨山大帝 2011-08-11
  • 打赏
  • 举报
回复
"这个函数用于大概数百万个6-20长度的字符串集合,查询其中每个字符串在另外一个数百万个6-20长度的字符串集合中是否存在只有一个位置不一样的字符串"

没看出来. --> "考虑到实际需求,只考虑等长字符串的比较。"

DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 lost_painting 的回复:]

看了楼主13楼的进一步对需求的分析.

"除了根据长度进行预分类"

这个预分类楼主认识是正确的吗?

AAABBB 与 AAABBBC 不是"两个字符串是否有且仅有一个字符的差异" 吗?

AAAABB 与 AAAABBB 不是"两个字符串是否有且仅有一个字符的差异" 吗?
[/Quote]

考虑到实际需求,只考虑等长字符串的比较。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 fangxinggood 的回复:]

多线程并行比较。按照你上面的说法,两个字符串之间的比较也就那样了。
[/Quote]

多线程已经实现了。谢谢。
鸭梨山大帝 2011-08-11
  • 打赏
  • 举报
回复
看了楼主13楼的进一步对需求的分析.

"除了根据长度进行预分类"

这个预分类楼主认识是正确的吗?

AAABBB 与 AAABBBC 不是"两个字符串是否有且仅有一个字符的差异" 吗?

AAAABB 与 AAAABBB 不是"两个字符串是否有且仅有一个字符的差异" 吗?

机器人 2011-08-11
  • 打赏
  • 举报
回复
多线程并行比较。按照你上面的说法,两个字符串之间的比较也就那样了。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
说明一下,这个函数用于大概数百万个6-20长度的字符串集合,查询其中每个字符串在另外一个数百万个6-20长度的字符串集合中是否存在只有一个位置不一样的字符串。除了根据长度进行预分类,还有什么加速的方法,也可以给分。
DreamTiger 2011-08-11
  • 打赏
  • 举报
回复
我写了一个unsafe的,还能更快么?


public static unsafe bool IsMutationOne(string seq1, string seq2)
{
int len = seq1.Length;
if (len != seq2.Length)
{
return false;
}

fixed (char* p1 = seq1)
fixed (char* p2 = seq2)
{
for (int i = 0; i < len; i++)
{
if (p1[i] != p2[i])
{
for (int j = i + 1; j < len; j++)
{
if (p1[j] != p2[j])
{
return false;
}
}
return true;
}
}
}

return false;
}
鸭梨山大帝 2011-08-11
  • 打赏
  • 举报
回复
楼主弄没弄清楚自己是不是真的要 "两个字符串是否有且仅有一个字符的差异" 还是 "两个等长的字符串是否有且仅有一个字符的差异"

{
return false;
}"

相差一个字符串长度也算一个字符串的差异.

" if (seq1.Length != seq2.Length)
{
return false;
}
"

这句话的判断本身就是错的.

AAABBBC 跟 AAABBB 不是一个字符串差异?

如果是等长的字符串比较,有必要开个帖子来讨论?


加载更多回复(2)

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧