后缀自动机SAM

附:本文参考(后缀自动机学习总结)[http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html]

先感性认知一下
这是一个建好的 字符串ACADD的SAM 示意图
kAv36O.jpg

每一个节点要维护的东西如下

  • Sigma
    常数,表示字符的种类数,比如维护小写字母字符串时为26
  • son[1 ~ Sigma](上图实线箭头) 子节点的指针
  • link(上图的虚线箭头)
    上一个可以接收后缀的结点
    注意link不是该点的父结点!(因为一个点有可能是多个点的儿子)
  • len
    从根结点走到当前点,最多需要多少步

SAM性质:

  • 从root到任意结点p的每条路径上的字符组成的字符串,都是当前串t的子串.
  • 因为满足性质一,所以如果当前结点p是可以接收新后缀的结点(被link指向),那么从root到任意结点p的每条路径上的字符组成的字符串,都是必定是当前串t的后缀.
  • 如果结点p可以接收新的后缀,那么p的link指向的结点也可以接收后缀,反过来就不行.

可以推出

  • 按照字典序遍历SAM可得到所有子串(是去重的 当然也可以通过记录节点的size来维护)
  • 从最后加入的一个点(肯定是原字符串的末尾节点嘛)向前找link 找到的就是所有的后缀结尾

然后就是建图辽
由于每一步都是一样的
在这里直接从一半开始建

现在要插入一个新的点np

  • STEP1
    对于一个已经建了一半的SAM 找到它最后一个被插入的点p(因为这个点必然可接受后缀
    然后用p向前跳link 直到被跳到的点满足有 np表示的字符的儿子指针

那如果最后跳到了一个 有 np表示字符的 儿子指针 的p 那可怎么办?
(这样的话 那个儿子表示的意思就重复了啊!

  • STEP2
    设那个已经有的儿子为q 如果q.len是p.len+1
    说明这个点表示的字符串可以代替p表示的字符串
    把p的link连到q上 (不想直接去重 把q的size++就好了
    (其实这个判定只是一个省节点的优化,直接复制不会错)

但如果q.len > p.len + 1的话
就不能代替 而要新建一个点nq
参考博客中给出理由(这里的step就是上文的len)

这和上一种情况一样,也面临着q点是否可以当成x结点的问题.在上一种情况的描述中,我们可以知道, step[q]=step[p]+1可以保证q原本是从p的路径上来的,而且p和q之间不会夹杂其它字符,所以可以直接把q结点当成x结点.那么反过来, step[q]>step[p]+1,就说明p和q之间有可能会夹杂其它字符,这就不能保证把q当成x结点以后,到q的路径都是tx的后缀了,于是我们不能采取和前一种情况一样的做法.但是,我们可以模仿前一种情况的做法.

然后接下来要做的事情相当麻烦。。
要复制到nq上的信息:son; link(nq.link = p);
另外的信息:nq.len = p.len + 1; nq.size = 1; q.link = nq; np.link = nq;
最后把p按link向上跳,把所有的son[np] = q的点的儿子指针都指到nq上

几道题
[AHOI2013]差异
把SAM当图看 题里那个式子就是路径长度嘛。。

Standing Out from the Herd
广义SAM
其实就是加上这个

    if(sam[last].ch[c] && sam[last].len + 1 == sam[sam[last].ch[c]].len){
        last = sam[last].ch[c];
        sam[last].flag = -1;
        return ;
    }

[NOI2016]优秀的拆分
后缀数组的题 正向维护一个SA 逆向维护一个SA
题解

[NOI2015]品酒大会
感觉像SAM裸题
那个inf设得我丧心病狂
也是把SAM当图看
建完sam后DP一下最大值最小值
ans必然是maxmax或minmin

<think>好的,用户想查找与SAM相关的代码示例或实现。首先,我需要明确SAM指的是什么。根据用户提供的引用[1],SAM指的是Security Account Manager,它是Windows系统中存储用户账户安全信息的数据库,包括登录密码的哈希值。所以用户可能是在询问如何通过编程访问SAM数据库,例如提取密码哈希之类的操作。 接下来,我需要考虑如何生成相关的代码示例。不过需要注意的是,直接访问SAM数据库通常需要系统级权限,并且可能涉及安全风险或法律问题。因此,在提供代码示例时,必须强调这些注意事项,并建议仅在合法授权的环境下使用。 用户提供的引用[1]中提到,Hash-dumping程序会访问SAM数据库来获取用户密码的哈希。因此,可能的代码示例可能涉及如何通过Windows API或工具(如mimikatz)来提取这些哈希。但编写这样的代码可能比较复杂,而且涉及到系统底层的操作,比如使用Windows的本地安全机构(LSA)或其他系统调用。 此外,引用[2]提到关于API契约的问题,虽然与SAM无直接关系,但可能在代码实现时需要考虑接口的稳定性,但这里可能不需要深入讨论。 因此,回答应该包括以下几点: 1. 解释SAM的作用和相关技术背景。 2. 提供可能的代码示例或工具,如使用Python调用Windows API或使用现有工具。 3. 强调安全和法律注意事项。 4. 生成相关问题,帮助用户进一步了解SAM相关的编程实现或安全考虑。 需要确保代码示例正确,并且符合用户要求的格式,比如使用$...$和$$...$$来包裹数学公式,但在这个问题中可能涉及较少数学内容。同时,保持回答结构清晰,分步骤说明,并添加引用标识到引用[1]。 最后,生成的相关问题应该围绕SAM的实现细节、安全防护措施、不同编程语言的实现方法等展开,以帮助用户深入理解。</think>### 与SAM相关的代码实现说明 Windows的`Security Account Manager (SAM)`数据库存储了本地用户的凭据信息,访问它通常需要**系统级权限**和底层API调用。以下是两种常见实现方向及注意事项: --- #### 1. 通过Windows API间接访问 需使用`Windows本地安全机构(LSA)`相关函数,以下为C++示例片段: ```cpp #include <windows.h> #include <ntsecapi.h> // 初始化LSA连接 LSA_HANDLE GetLsaPolicy() { LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0}; LSA_HANDLE lsahPolicyHandle; NTSTATUS status = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &lsahPolicyHandle ); if (status != ERROR_SUCCESS) { // 错误处理 } return lsahPolicyHandle; } ``` 此代码需链接`Advapi32.lib`,并需管理员权限运行[^1]。 --- #### 2. 使用工具或脚本提取哈希 直接读取SAM文件(位于`%systemroot%/system32/config/sam`)需要绕过系统保护,通常借助工具如`mimikatz`或`impacket`库。以下是Python使用`impacket`的示例: ```python from impacket.secretsdump import LocalOperations sam_file = "C:/Windows/System32/config/SAM" system_file = "C:/Windows/System32/config/SYSTEM" local_ops = LocalOperations(sam_file) hashes = local_ops.dump() print(hashes) ``` 需注意:此代码需在**特权环境**下运行,且可能触发安全软件告警。 --- ### 注意事项 - **权限要求**:访问SAM需`SYSTEM`权限或物理磁盘提取文件 - **法律风险**:未经授权的访问违反计算机安全法律 - **安全防护**:现代系统通过`Windows Credential Guard`强化SAM保护 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值