Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
420aac72
Commit
420aac72
authored
Apr 01, 2020
by
antirez
Browse files
LCS: implement range indexes option.
parent
a518a9a7
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/t_string.c
View file @
420aac72
...
@@ -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