Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
b3400559
You need to sign in or sign up before continuing.
Commit
b3400559
authored
Apr 01, 2020
by
antirez
Browse files
LCS: implement range indexes option.
parent
1010c1b4
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/t_string.c
View file @
b3400559
...
@@ -482,7 +482,7 @@ void strlenCommand(client *c) {
...
@@ -482,7 +482,7 @@ void strlenCommand(client *c) {
/* LCS -- Longest common subsequence.
/* LCS -- Longest common subsequence.
*
*
* LCS
[LEN]
[IDX] [STOREIDX <key>] STRINGS <string> <string> */
* LCS [IDX] [STOREIDX <key>] STRINGS <string> <string> */
void
lcsCommand
(
client
*
c
)
{
void
lcsCommand
(
client
*
c
)
{
uint32_t
i
,
j
;
uint32_t
i
,
j
;
sds
a
=
NULL
,
b
=
NULL
;
sds
a
=
NULL
,
b
=
NULL
;
...
@@ -495,12 +495,12 @@ void lcsCommand(client *c) {
...
@@ -495,12 +495,12 @@ void lcsCommand(client *c) {
if
(
!
strcasecmp
(
opt
,
"IDX"
))
{
if
(
!
strcasecmp
(
opt
,
"IDX"
))
{
getidx
=
1
;
getidx
=
1
;
}
else
if
(
!
strcasecmp
(
opt
,
"LEN"
))
{
getlen
=
1
;
}
else
if
(
!
strcasecmp
(
opt
,
"STOREIDX"
)
&&
moreargs
)
{
}
else
if
(
!
strcasecmp
(
opt
,
"STOREIDX"
)
&&
moreargs
)
{
getidx
=
1
;
getidx
=
1
;
idxkey
=
c
->
argv
[
j
+
1
];
idxkey
=
c
->
argv
[
j
+
1
];
j
++
;
j
++
;
}
else
if
(
!
strcasecmp
(
opt
,
"LEN"
))
{
getlen
++
;
}
else
if
(
!
strcasecmp
(
opt
,
"STRINGS"
))
{
}
else
if
(
!
strcasecmp
(
opt
,
"STRINGS"
))
{
if
(
moreargs
!=
2
)
{
if
(
moreargs
!=
2
)
{
addReplyError
(
c
,
"LCS requires exactly two strings"
);
addReplyError
(
c
,
"LCS requires exactly two strings"
);
...
@@ -515,10 +515,17 @@ void lcsCommand(client *c) {
...
@@ -515,10 +515,17 @@ void lcsCommand(client *c) {
}
}
}
}
/* Complain if the user
didn't pass the STRING option
. */
/* Complain if the user
passed ambiguous parameters
. */
if
(
a
==
NULL
)
{
if
(
a
==
NULL
)
{
addReplyError
(
c
,
"STRINGS <string-a> <string-b> is mandatory"
);
addReplyError
(
c
,
"STRINGS <string-a> <string-b> is mandatory"
);
return
;
return
;
}
else
if
(
getlen
&&
(
getidx
&&
idxkey
==
NULL
))
{
addReplyError
(
c
,
"If you want both the LEN and indexes, please "
"store the indexes into a key with STOREIDX. However note "
"that the IDX output also includes both the LCS string and "
"its length"
);
return
;
}
}
/* Compute the LCS using the vanilla dynamic programming technique of
/* Compute the LCS using the vanilla dynamic programming technique of
...
@@ -559,21 +566,62 @@ void lcsCommand(client *c) {
...
@@ -559,21 +566,62 @@ void lcsCommand(client *c) {
/* Store the actual LCS string in "result" if needed. We create
/* Store the actual LCS string in "result" if needed. We create
* it backward, but the length is already known, we store it into idx. */
* it backward, but the length is already known, we store it into idx. */
uint32_t
idx
=
LCS
(
alen
,
blen
);
uint32_t
idx
=
LCS
(
alen
,
blen
);
sds
result
=
NULL
;
sds
result
=
NULL
;
/* Resulting LCS string. */
void
*
arraylenptr
=
NULL
;
/* Deffered length of the array for IDX. */
uint32_t
arange_start
=
alen
,
/* alen signals that values are not set. */
arange_end
=
0
,
brange_start
=
0
,
brange_end
=
0
;
/* Do we need to compute the actual LCS string? Allocate it in that case. */
/* Do we need to compute the actual LCS string? Allocate it in that case. */
int
computelcs
=
getidx
||
!
getlen
;
int
computelcs
=
getidx
||
!
getlen
;
if
(
computelcs
)
result
=
sdsnewlen
(
SDS_NOINIT
,
idx
);
if
(
computelcs
)
result
=
sdsnewlen
(
SDS_NOINIT
,
idx
);
/* Start with a deferred array if we have to emit the ranges. */
uint32_t
arraylen
=
0
;
/* Number of ranges emitted in the array. */
if
(
getidx
&&
idxkey
==
NULL
)
arraylenptr
=
addReplyDeferredLen
(
c
);
i
=
alen
,
j
=
blen
;
i
=
alen
,
j
=
blen
;
while
(
computelcs
&&
i
>
0
&&
j
>
0
)
{
while
(
computelcs
&&
i
>
0
&&
j
>
0
)
{
if
(
a
[
i
-
1
]
==
b
[
j
-
1
])
{
if
(
a
[
i
-
1
]
==
b
[
j
-
1
])
{
/* If there is a match, store the character and reduce
/* If there is a match, store the character and reduce
* the indexes to look for a new match. */
* the indexes to look for a new match. */
result
[
idx
-
1
]
=
a
[
i
-
1
];
result
[
idx
-
1
]
=
a
[
i
-
1
];
idx
--
;
/* Track the current range. */
i
--
;
int
emit_range
=
0
;
j
--
;
if
(
arange_start
==
alen
)
{
arange_start
=
i
-
1
;
arange_end
=
i
-
1
;
brange_start
=
j
-
1
;
brange_end
=
j
-
1
;
if
(
i
==
0
||
j
==
0
)
emit_range
=
1
;
}
else
{
/* Let's see if we can extend the range backward since
* it is contiguous. */
if
(
arange_start
==
i
&&
brange_start
==
j
)
{
arange_start
--
;
brange_start
--
;
}
else
{
emit_range
=
1
;
}
}
/* Emit the current range if needed. */
if
(
emit_range
)
{
if
(
arraylenptr
)
{
addReplyArrayLen
(
c
,
2
);
addReplyArrayLen
(
c
,
2
);
addReplyLongLong
(
c
,
arange_start
);
addReplyLongLong
(
c
,
arange_end
);
addReplyArrayLen
(
c
,
2
);
addReplyLongLong
(
c
,
brange_start
);
addReplyLongLong
(
c
,
brange_end
);
}
arange_start
=
alen
;
/* Restart at the next match. */
arraylen
++
;
}
idx
--
;
i
--
;
j
--
;
}
else
{
}
else
{
/* Otherwise reduce i and j depending on the largest
/* Otherwise reduce i and j depending on the largest
* LCS between, to understand what direction we need to go. */
* LCS between, to understand what direction we need to go. */
...
@@ -589,7 +637,9 @@ void lcsCommand(client *c) {
...
@@ -589,7 +637,9 @@ void lcsCommand(client *c) {
/* Signal modified key, increment dirty, ... */
/* Signal modified key, increment dirty, ... */
/* Reply depending on the given options. */
/* Reply depending on the given options. */
if
(
getlen
)
{
if
(
arraylenptr
)
{
setDeferredArrayLen
(
c
,
arraylenptr
,
arraylen
);
}
else
if
(
getlen
)
{
addReplyLongLong
(
c
,
LCS
(
alen
,
blen
));
addReplyLongLong
(
c
,
LCS
(
alen
,
blen
));
}
else
{
}
else
{
addReplyBulkSds
(
c
,
result
);
addReplyBulkSds
(
c
,
result
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment