• ICS计算系统概论实验3—LC3汇编代码实现最长重复子字符串Longest-duplicate-substring


    Lab03 Longest-duplicate-substring

    Purpose

    子字符串是字符串中至少出现一次的连续字符序列。重复子字符串是一种由相同字符组成的子字符串。例如,“aabbbc”的重复子字符串是“aa”,“bbb”和“c”。
    给定一个字符串及其长度,计算出它最长的重复子字符串的长度。

    condition:
    请注意,(1<=N<=100) 将存储在 x3100 中,并且 的每个字符都存储在从地址 x3101 开始的连续内存位置。
    您可以假设仅包含 a-z 和 A-Z。
    任务:将输出、最长的重复子字符串存储在 x3050 中。
    R0-R7 初始设置为零,程序应从 x3000 开始。

    several examples:

    Memory addressx3050x3100x3101x3102x3103x3104x3105x3106
    example 1RESULT=3NUM=6aabbbc
    example 2RESULT=4NUM=5ZZZZz
    example 3RESULT=3NUM=6aabaaa

    Principles

    Key issues:

    如何记录最长重复的数量

    要记录最长的重复数量,我们对字符串进行分析,可以看出,任意一个字符串,我们取其具有连续相同子串的模式,在任一时刻可以看作三部分,如xxxyzzz、xxxyzyzwww等,即两部分连续重复子串间隔一部分不连续的子串,即任意时刻我们最多只需要两个变量分别保存最长长度以及当前统计的连续重复子串长度,当这个相同连续被打破即出现不同字符时,比较一下两个长度,取其较大值。所以统计相同字符数量时使用两个寄存器:R2,R3,R2记录最长长度,R3记录当前子串相同字符长度,当判断到不同字符时,R3停止记录,跳转至比较R2与R3的大小,取其较大值存至R3中,并将R3清零后继续向后读取字符串,直至结束。

    如何判断两个字符是否相同

    在使用其他高级语言编程统计重复字符时,通常会用到双指针进行记录,所以联系到汇编语言,我们可以使用两个寄存器R5、R6作为两个指针,初始时分别指向第一个字符和第二个字符,每次判断是否满足R5==R6,满足则当前长度+1并后移指针,否则说明两个字符不相同,当前长度不变并将指针后移,直至R6指向最后一个字符,程序也相应结束。

    Flow chart:

    yes
    yes
    no
    no
    yes
    yes
    no
    no
    R0<-mem[x3100]
    R0<-R0-2
    R1<-x3101
    R5<-mem[R1]
    R6<-mem[R1+1]
    NOT R5<-R5
    R5<-R5+1
    R5<-R5+R6
    if R5 == 0
    R3<-R3+1
    R0 <- R0-1
    if R0<0
    R1<-R1+1
    R4<- NOT R3
    R4<- R4+1
    R4<-R2+R4
    if R4<=0
    R2<-R3
    R3<-0
    R2<-R2+1
    mem[x3050]<-R2
    HALT
    R7<-R0+1
    if R7==0
    R3<-0

    Procedure

    初始化:R0存放字符串总长度,因为使用双指针比较字符,所以R0=R0-2作为循环的总次数,R1存放字符串的起始地址,R2,R3分别存放最大长度和当前长度,R5,R6分别记录前一个字符和后一个字符,作为双指针向前移动
    循环:将R5与R6相减用于比较当前两个字符是否相等,相等则R3+1,不相等则跳转比较,令R2=max(R2,R3),再回到循环,判断循环计数R0是否满足R0>0,满足则R1+1,R5,R6对应+1,即向前读入一个字符进行比较,重复循环过程。
    结束:R0<0时跳转至存储,存储之前需要再做一次R2与R3的比较,将最大值放入R2中,最后将R2的值存入x3050内存单元

    Result

    Debug:

    过程中遇到的主要问题有:
    对于下列两个样例

    89:sdsdsdssssssssdsdsfdjkkkkkkkkkkdlslsjdfnnnnnsdswiejdjskjsfkdsfdfskdksknsnsjsndllbbbbbdfsd:10

    92:sdsdsdssssssssdsdsfdjkkkkkkkkkkdlslsjdfnnnnnsdswiejdjskjsfkdsfdfskdksknsnsjsndllbbbbbdfsdddd:10

    分别输出10 以及 13,结果如下图所示,两个样例最长的子串都应该是连续的10个k,两个样例的区别仅在于最后的ddd,然而输出结果却不同
    在这里插入图片描述
    在调试模式中发现,在处理最后的子串时R3由8变为9后,遇到了不同的子串却没有清零,而是继续增加,即由9到10

    在这里插入图片描述

    在这里插入图片描述
    检查发现代码中对R3的清零操作仅当R2

    在这里插入图片描述
    所以上述代码应改为如下图所示:
    在这里插入图片描述
    并且,由于我的程序是通过检测到不同字符时,跳转至比较当前R3正在记录的长度与R2中记录的最长长度并取最大值存入R2中,所以在程序要结束时应该再比较一次,因为可能存最后结尾的子串是最长的重复子串的情况。

    在这里插入图片描述

    Judge:

    在本地 LC3Tool \text{LC3Tool} LC3Tool调试完毕后,将代码整理如下:用于网站在线 lc3 \text{lc3} lc3评测

    .ORIG x3000
    LDI R0, NUM;
    ADD R0, R0, #-2;循环次数
    LD R1, DATA ; R1 is the pointer of the string
    ADD R2, R2, #0;计数器
    ADD R3, R3, #0;
    
    CHECK LDR R5, R1, #0;第一个字符
          LDR R6, R1, #1;第二个字符
          NOT R5, R5;     
          ADD R5, R5, #1;R5取反
          ADD R5, R5, R6;相加为0说明相同
          BRz CNT      ;
          BRnp CMP      ;
          
    CNT ADD R3, R3, #1  ;计数
    LOOP ADD R0, R0, #-1 ;循环次数
        BRn BREAK       ;结束
        ADD R1, R1, #1  ;后移
        BR CHECK    
    CMP NOT R4, R3;     
        ADD R4, R4, #1  ;R3取反
        ADD R4, R2, R4  ;
        BRnz MAX         ;R2
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    评测结果如下,正常运行,输出正确。

    在这里插入图片描述

  • 相关阅读:
    【面试刷题】——Qt事件处理器级别的划分
    【.net core】解决无法下载wgt文件问题
    MyBatisPlus 基础Mapperr接口:增删改查
    Linux基础复习及常用命令的使用
    springMVC的简单数据绑定
    栈和队列专项练习
    make命令应用
    wxpython:wx.grid 表格显示 Excel xlsx文件
    牛客在线编程101-17 二分查找-I
    mybatis insert 插入字段为空解决办法
  • 原文地址:https://blog.csdn.net/weixin_56462041/article/details/128155488