zoukankan      html  css  js  c++  java
  • 后缀树求最长子字符串

    问题描述:

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

    解题过程:

    这个问题最直接的解法就是变位词程序(《编程珠玑》2.4节)。如果将输入字符串存储在c[0..n-1]中,那么我们可能会使用类似下面的伪代码比较每个子串;

    复制代码
    maxlen = -1;
    for i = [0, n]
        for j = (i, n)
            if (thislen = comlen(&c[i], &c[j])) > maxlen
                maxlen = thislen;
                maxi = i;
                maxj = j;
    复制代码

    comlen函数返回其两个参数字符串中共同部分的长度,从第一个字符开始比较:

    复制代码
      int comlen(char* p, char* q)
      {
          int i = 0;
          while (*q && (*p++ == *q++))
          {
              i++;
          }
          return i;
      }
    复制代码

    该算法需要的时间复杂度为o(n^2)。可以用散列表搜索短语中的单词来实现提速,但是这里有另一个跟好的算法:

    我们将使用“后缀数组”的简单简单结构。

    复制代码
      #define MAXN 50000
    
          char c[MAXN];
          char* a[MAXN];
          char ch;
          int n = 0;
          while ((ch = getchar()) != EOF)
          {
              a[n] = &c[n];
              c[n++] = ch;
          }
          c[n] = 0;
    复制代码

    如果c中存储的是“banana”,该数组的后缀数组内容就是:

    a[0] = "banana"

    a[1] = "anana"

    a[2] = "nana"

    ……

    然后对其进行排序,可以使用qsort来进行,对排序完的数组只需要一边扫描,统计相邻单词共有子串的长度。

    思路就是这样,完整的代码如下:

    复制代码
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
    
      #define MAXN 50000
    
      int comlen(char* p, char* q)
      {
          int i = 0;
          while (*q && (*p++ == *q++))
          {
              i++;
          }
          return i;
      }
    
      int cstring_cmp(const void *a, const void *b)
      {
          const char **ia = (const char **)a;
          const char **ib = (const char **)b;
          return strcmp(*ia, *ib);
      }
    
      int main()
      {
          char c[MAXN];
          char* a[MAXN];
          char ch;
          int n = 0;
          while ((ch = getchar()) != EOF)
          {
              a[n] = &c[n];
              c[n++] = ch;
          }
          c[n] = 0;
    
          qsort(a, n, sizeof(char*), cstring_cmp);
    
          int maxlen = 0;
          int len = 0;
          int maxi = 0;
          for (int i = 0; i < n - 1; i++)
        {
              len = comlen(a[i], a[i + 1]);
              if (len > maxlen)
              {
                  maxlen = len;
                  maxi = i;
              }
          }
    
          printf("maxlen:%d\tmax string:\t", maxlen);
          char ch_tmp;
          for (int i = 0; i < maxlen; i++)
          {
              ch_tmp = *(a[maxi] + i);
              printf("%c", ch_tmp);
          }
          printf("\n");
    
          return 0;
      }
    复制代码
  • 相关阅读:
    蛋糕多少钱?
    【FJOI2015】金币换位问题
    撞车
    【BZOJ 1097】旅游景点atr
    codeforces 434D
    codeforces 480D
    bzoj网络流
    bzoj2039
    bzoj1927
    bzoj1070
  • 原文地址:https://www.cnblogs.com/mfryf/p/2648680.html
Copyright © 2011-2022 走看看