zoukankan      html  css  js  c++  java
  • 编程珠玑:用后缀数组寻找最长重复字符串

    1.基本概念

    子串:字符串 S 的子串 r[i..j] , i ≤ j ,表示 r 串中从 i 到 j 这一段,就是顺次排列 r[i],r[i+1],...,r[j] 形成的字符串。

    后缀:后缀是指从某个位置 i 开始到整个串末尾结束的一个特殊子串。字符串 r 的从 第 i 个字 符 开 始 的 后 缀 表 示 为 Suffix(i) ,也 就 是Suffix(i)=r[i..len(r)] 。

    后缀数组:后缀数组 SA 是一个一维数组,它保存 1..n 的某个排列 SA[1] ,SA[2] , …… , SA[n] ,并且保证 Suffix(SA[i]) < Suffix(SA[i+1]) , 1 ≤ i<n 。也就是将 S 的 n 个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入 SA 中。

     

     

    2.问题描述

    给定一个文本文件作为输入,查找其中最长的重复子字符串。例如,"Ask not what your country can do for you, but what you can do for your
    country"中最长的重复字符串是“can do for you”,第二长的是"your country"。

     

    3.解决思路

    利用后缀数组。首先输入一个字符串到c[]中,例如“banana”,读入时我们队指针的数组a进行初始化,使得每个元素指向输入字符串的相应字符,则元素a[0]指向整个字符串,下一个元素指向从第二个字符开始的数组后缀,等等。对于前面的输入字符串,该数组能够表示下面这些后缀:

    a[0]:banana
    a[1]:anana
    a[2]:nana
    a[3]:ana
    a[4]:na
    a[5]:a

    如果某个长字符串在数组a中出现两次,那么她将出现在两个不同的后缀中,因此我们队数组排序以寻找相同的后缀,下面将上面的数组a进行数组排序,结果如下

    a[0]:a
    a[1]:ana
    a[2]:anana
    a[3]:banana
    a[4]:na
    a[5]:nana

    然后我们就可以扫描数组,通过比较相邻元素来找出最长的重复字串,如上为"ana"

     

    4.代码实现

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXN 5000000
    char c[MAXN], *a[MAXN];
    
    
    int comlen(char *p, char *q)
    {
        int i = 0;
        while(*p && (*p++ == *q++))
        {
                 i++;
        }
        return i;
    }
    
    int pstrcmp(const void *a, const void *b)
    {
        return  strcmp(*(char* const*)a, *(char* const*)b); //这里的 *(char* const*)a中的a 为指向指针的指针,
    }                                                       //首先(char* const*)a 将变量a强制转换成char类型的指向指针的const指针,
    //然后用*进行 地址解引用
    int main() { char ch; int i,n=0,maxlen=-1,maxi; while((ch = getchar()) != EOF && ch != '\n') { a[n] = &c[n]; c[n++] = ch; } c[n]='\0'; qsort(a, n , sizeof(char *), pstrcmp); for(i = 0;i < n-1; i++) { if(comlen(a[i], a[i+1]) > maxlen) { maxlen = comlen(a[i], a[i+1]); maxi = i; } } printf("%.*s\n", maxlen, a[maxi]); system("pause"); return 0; }


     

     

  • 相关阅读:
    文本切换器(TextSwitcher)的功能和用法
    图像切换器(ImageSwitcer)的功能与用法
    ViewSwitcher的功能与用法
    HTTP协议-get请求与post请求的区别
    HTTP协议缓存
    HTTP协议详解
    Vue.js----更换头像不实时更新问题
    Vue.js----date与时间戳的转换(unixTime)Moment.js让日期处理变得更简单
    Let's Encrypt 免费通配 https 签名证书 安装方法
    小程序Openid 获取,服务器 encryptedData 解密 遇到的坑
  • 原文地址:https://www.cnblogs.com/biyeymyhjob/p/2639572.html
Copyright © 2011-2022 走看看