最长重复数组

来源:互联网 发布:淘宝网苹果7都下架了 编辑:程序博客网 时间:2024/06/01 11:05

最长重复数组,具体可以参考编程珠玑15章

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

方法一:双重for循环依次比较每个字符串,找到最长重复子字符串

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>

  4. //找到两个字符串公共部分的长度
  5. int comlen(char *p, char *q)
  6. {    
  7.     int i = 0;
  8.     while (*&& (*p++ == *q++))
  9.     {
  10.         i++;
  11.     }
  12.     return i;
  13. }

  14. int main()
  15. { 
  16.     int i, j;
  17.     int maxi, maxj;
  18.     int currentlen, maxlen = -1;
  19.     char *str = "ask not what your country can do for you, but what you can do for your country";
  20.     int length = strlen(str);

  21.     for(= 0; i < length; i++)
  22.     {
  23.         for(= i + 1; j < length; j++)
  24.         {
  25.             currentlen = comlen(str + i, str + j);
  26.             if(currentlen > maxlen)
  27.             {
  28.                 maxlen = currentlen;
  29.                 maxi = i;//i标记了最长公共子串开始的位置
  30.                 maxj = j;
  31.             }
  32.         }
  33.     }

  34.     for(= 0; i < maxlen; i++)
  35.     {
  36.         printf("%c", str[maxi + i]);
  37.     }
  38.     printf("n");
  39.     return 0;
  40. }

方法二:采用后缀数组来处理该问题
    我们的程序最多处理MAXN个字符,这些字符存储在数组c中。
    #define MAXN  50000
    char c[MAXN], *a[MAXN];
    我们使用一个称为“后缀数组”的数据结构,这个结构是一个字符指针数组,记为a。读取输入时,我们对a进行初始化,使得每个元素指向输入字符串中的相应字符:
    while(ch  = getchar() != EOF)
    {
            a[n] = &c[n];
            c[n] = ch;
    }
    c[n] = 0;

    元素a[0]指向整个字符串,下一个元素指向从第二个字符开始的数组后缀,等等。对于输入字符串“banana”,该数组能够表示如下后缀:
                            char *a="banana"
                            a[0]=banana
                            a[1]=anana
                            a[2]=nana
                            a[3]=ana
                            a[4]=na
                            a[5]=a
    如果某个长字符串在数组c中出现了两次,那么它将出现在两个不同的后缀中,因此我们队数组进行排序以寻找相同的后缀。“banana”数组排序为:
                            a[0]=a
                            a[1]=ana
                            a[2]=anana
                            a[3]=banana
                            a[4]=na
                            a[5]=nana
    然后就可以扫描数组,通过比较相邻元素来找出最长的重复字符串。
    该方法由于排序的存在,时间复杂度为O(nlogn)。

#include <stdlib.h>#include <string.h>#include <stdio.h>//只能比较字符串,两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇''为止。int pstrcmp(const void *p, const void *q){return strcmp(*(char **)p, *(char **)q);}int comlen(char *p, char *q)//返回两个参数共同部分的长度 {    int i = 0;while (*p && (*p++ == *q++))i++;return i;}#define M 1#define MAXN 5000000char c[MAXN], *a[MAXN];int main(){ int i, ch, n = 0, maxi, maxlen = -1;while ((ch = getchar()) != EOF) {a[n] = &c[n];c[n++] = ch;}c[n] = 0;qsort(a, n, sizeof(char *), pstrcmp);//快速排序 for (i = 0; i <n-M; i++)
          {if (comlen(a[i], a[i+M]) > maxlen) //比较相邻字符串相同个数 {maxlen = comlen(a[i], a[i+M]);maxi = i;}
            }printf("%.*s\n", maxlen, a[maxi]);return 0;}
0 0
原创粉丝点击