1.初步实现
//在字符串haystack中查找字符串needle最后一次出现的位置,
//找到返回needle在haystack中的索引值,否则返回0
//(注:Pascal/Delphi中string类型的索引从1开始).
function strrstr(const haystack, needle: string): Integer;
var
i, j, nLen: Integer;
begin
strrstr:= 0;
i:= Length(haystack);
nLen:= Length(needle);
j:= nLen;
if(i = 0) or (j = 0) or (j > i)then
Exit;
repeat
if haystack[i] = needle[j] then
begin
if j = 1 then
begin
strrstr:= i;
Exit;
end;
Dec(j);
end
else j:= nLen;
Dec(i);
until i = 0
end;
2.调用测试
var str: string;
begin
//0 //1 //2
//1234567890123456789012345
str:= 'Touch fish make me happy!';
Writeln(strrstr(str, 'happy'));
Writeln(strrstr(str, 'me'));
Writeln(strrstr(str, 'm'));
Writeln(strrstr(str, 'fish'));
Writeln('---------------------------------------');
Writeln(strrstr(str, 'Study make me happy!'));
Writeln(strrstr(str, 'happy?'));
Writeln(strrstr(str, 'mee'));
Writeln(strrstr(str, 'touch'));
Readln;
end.
3.运行结果
😃
3.改进函数
函数逻辑和运行结果都是正确的,哪里可以改进呢?
函数中使用循环查找出haystack尾部与needle尾字符相等的字符后,索引needle中尾字符的j变量就递减,如果从haystack索引到的字符与当前使用j变量从needle中索引到的尾字符不等,j变量就要恢复成needle的最大索引值nLen,以让接下来从haystack中的匹配扫描重新从needle的末字符开始,显然只有在之前匹配到尾字符后j变量的值才会改变,后面匹配不上了才需要重置j变量的值成nLen,而不是每次循环中不管之前有没有匹配到只要本次没匹配到就重置j为nLen,这样在之前没匹配到的情况下,j仍旧等同为nLen,此时这步操作就是冗余的,带来不必要的性能消耗。
4.最终实现
//在字符串haystack中查找字符串needle最后一次出现的位置,
//找到返回needle在haystack中的索引值,否则返回0
//(注:Pascal/Delphi中string类型的索引从1开始).
function strrstr(const haystack, needle: string): Integer;
var i, j, nLen: Integer;
label ISOVER;
begin
strrstr:= 0;
i:= Length(haystack);
nLen:= Length(needle);
j:= nLen;
if(i = 0) or (j = 0) or (j > i) then
Exit;
repeat
if haystack[i] = needle[j] then
begin
GOTO ISOVER;
repeat
if haystack[i] = needle[j] then
begin
ISOVER:
if j = 1 then
begin
strrstr:= i;
Exit;
end;
Dec(j);
end
else
begin
j:= nLen;
Break;
end;
Dec(i);
until i = 0;
end;
Dec(i);
until i = 0;
end;
5.运行结果
😃