• J


    题目链接:https://cn.vjudge.net/contest/283743#problem/J

    题目大意:给你两个字符串,问你两个字符串的最长的公共子串。

    具体思路:把两个字符串合在一起,然后求后缀数组,按照排名之后的字符串,如果两个相邻的字符串的sa[i]和sa[i-1]分别属于两个字符串,那么这个就是题目允许的值之一,然后再从这些值里面找一个最大的输出就可以了。

    AC代码:

      1 #include<iostream>
      2 #include<stack>
      3 #include<cstring>
      4 #include<iomanip>
      5 #include<stdio.h>
      6 #include<algorithm>
      7 #include<cmath>
      8 using namespace std;
      9 # define ll long long
     10 # define inf 0x3f3f3f3f
     11 const int maxn = 5e5+100;
     12 int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn];
     13 int Rank[maxn];
     14 char ch[maxn];
     15 char str1[maxn];
     16 int sto[maxn];
     17 ll n;
     18 //sa[i]代表第i小的后缀位置,Rank[i]代表第i位置的后缀,排名第几小
     19 // height[i]代表排名第i个字符串和第i-1个字符串的相同前缀有多少个
     20 void cal()
     21 {
     22     for(int i = 0; i < 256; i++)
     23         cntA[i] = 0;
     24     for(int i = 1; i <= n; i++)
     25     {
     26         cntA[ch[i-1]]++;
     27     }
     28     for(int i = 1; i < 256; i++)
     29         cntA[i] += cntA[i-1];
     30     for(int i = n; i; i--)
     31         sa[cntA[ch[i-1]]--] = i;
     32     Rank[sa[1]] = 1;
     33     for(int i = 2; i <= n; i++)
     34     {
     35         Rank[sa[i]] = Rank[sa[i-1]];
     36         if(ch[sa[i]-1] != ch[sa[i-1]-1])
     37             Rank[sa[i]]++;
     38     }
     39     for(int l = 1; Rank[sa[n]] < n; l <<= 1)
     40     {
     41         memset(cntA, 0, sizeof(cntA));
     42         memset(cntB, 0, sizeof(cntB));
     43         for(int i = 1; i <= n; i++)
     44         {
     45             cntA[A[i] = Rank[i]]++;
     46             cntB[B[i] = (i+l <= n)?Rank[i+l]:0]++;
     47         }
     48         for(int i = 1; i <= n; i++)
     49             cntB[i] += cntB[i-1];
     50         for(int i = n; i; i--)
     51             tsa[cntB[B[i]]--] = i;
     52         for(int i = 1; i <= n; i++)
     53             cntA[i] += cntA[i-1];
     54         for(int i = n; i; i--)
     55             sa[cntA[A[tsa[i]]]--] = tsa[i];
     56         Rank[sa[1]]=1;
     57         for(int i = 2; i <= n; i++)
     58         {
     59             Rank[sa[i]] = Rank[sa[i-1]];
     60             if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]])
     61                 Rank[sa[i]]++;
     62         }
     63     }
     64     for(int i = 1, j = 0; i <= n; i++)
     65     {
     66         if(j)
     67             j--;
     68         while(ch[i+j-1] == ch[sa[Rank[i]-1] + j - 1])
     69             j++;
     70         height[Rank[i]] = j;
     71     }
     72 }
     73 int main()
     74 {
     75     scanf("%s",str1);
     76     int len1=strlen(str1);
     77     for(int i=0; i<len1; i++)
     78     {
     79         ch[i]=str1[i];
     80     }
     81     scanf("%s",str1);
     82     int len2=strlen(str1);
     83     for(int i=len1; i<len1+len2; i++)
     84     {
     85         ch[i]=str1[i-len1];
     86     }
     87     n=len1+len2;
     88     cal();
     89     int maxx=0;
     90     for(int i=2; i<=len1+len2; i++)
     91     {
     92         if(height[i]>maxx)
     93         {
     94             if(sa[i]>=1&&sa[i]<=len1&&sa[i-1]>=(1+len1)&&sa[i-1]<=len1+len2)
     95                 maxx=height[i];
     96             if(sa[i-1]>=1&&sa[i-1]<=len1&&sa[i]>=(1+len1)&&sa[i]<=len1+len2)
     97                 maxx=height[i];
     98         }
     99     }
    100     printf("%d
    ",maxx);
    101     return 0;
    102 }
  • 相关阅读:
    hdu 2527:Safe Or Unsafe(数据结构,哈夫曼树,求WPL)
    hdu 2019:数列有序!(数据结构,直接插入排序+折半插入排序)
    hdu 3791:二叉搜索树(数据结构,二叉搜索树 BST)
    hdu 3336:Count the string(数据结构,串,KMP算法)
    hdu 1022:Train Problem I(数据结构,栈,递归,dfs)
    hdu 2141:Can you find it?(数据结构,二分查找)
    hdu 1232:畅通工程(数据结构,树,并查集)
    hdu 2025:查找最大元素(水题,顺序查找)
    hdu 2857:Mirror and Light(计算几何,点关于直线的对称点,求两线段交点坐标)
    hdu 1174:爆头(计算几何,三维叉积求点到线的距离)
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10390384.html
Copyright © 2020-2023  润新知