zoukankan      html  css  js  c++  java
  • H

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

    题目大意:T组数据,给你一个字符串,然后让你求这个字符串的重复最多子串的次数。

    具体思路:论文题。

    https://www.cnblogs.com/staginner/archive/2012/02/06/2340521.html。

    rmq处理的是某区间内的最小的前缀长度,这样查询的时候直接找到这个区间内的最小值就可以了。

    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],dp[25][maxn];
     14 char ch[maxn];
     15 int sto[maxn];
     16 ll n;
     17 //sa[i]代表第i小的后缀位置,Rank[i]代表第i位置的后缀,排名第几小
     18 // height[i]代表排名第i个字符串和第i-1个字符串的相同前缀有多少个
     19 void cal()
     20 {
     21     for(int i = 0; i < 256; i++)
     22         cntA[i] = 0;
     23     //   cout<<1<<endl;
     24     //  cout<<n<<endl;
     25     for(int i = 1; i <= n; i++)
     26     {
     27         //cout<<ch[i-1]<<endl;
     28         cntA[ch[i-1]]++;
     29     }
     30     //  cout<<1<<endl;
     31     for(int i = 1; i < 256; i++)
     32         cntA[i] += cntA[i-1];
     33     for(int i = n; i; i--)
     34         sa[cntA[ch[i-1]]--] = i;
     35     Rank[sa[1]] = 1;
     36     for(int i = 2; i <= n; i++)
     37     {
     38         Rank[sa[i]] = Rank[sa[i-1]];
     39         if(ch[sa[i]-1] != ch[sa[i-1]-1])
     40             Rank[sa[i]]++;
     41     }
     42     for(int l = 1; Rank[sa[n]] < n; l <<= 1)
     43     {
     44         memset(cntA, 0, sizeof(cntA));
     45         memset(cntB, 0, sizeof(cntB));
     46         for(int i = 1; i <= n; i++)
     47         {
     48             cntA[A[i] = Rank[i]]++;
     49             cntB[B[i] = (i+l <= n)?Rank[i+l]:0]++;
     50         }
     51         for(int i = 1; i <= n; i++)
     52             cntB[i] += cntB[i-1];
     53         for(int i = n; i; i--)
     54             tsa[cntB[B[i]]--] = i;
     55         for(int i = 1; i <= n; i++)
     56             cntA[i] += cntA[i-1];
     57         for(int i = n; i; i--)
     58             sa[cntA[A[tsa[i]]]--] = tsa[i];
     59         Rank[sa[1]]=1;
     60         for(int i = 2; i <= n; i++)
     61         {
     62             Rank[sa[i]] = Rank[sa[i-1]];
     63             if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]])
     64                 Rank[sa[i]]++;
     65         }
     66     }
     67     for(int i = 1, j = 0; i <= n; i++)
     68     {
     69         if(j)
     70             j--;
     71         while(ch[i+j-1] == ch[sa[Rank[i]-1] + j - 1])
     72             j++;
     73         height[Rank[i]] = j;
     74     }
     75 }
     76 void rmq()
     77 {
     78     for(int i=1; i<=n; i++)
     79     {
     80         dp[0][i]=height[i];
     81     }
     82     int tmp=log2(n);
     83     for(int i=1; i<=tmp; i++)
     84     {
     85         for(int j=1; (1<<i)+j-1<=n; j++)
     86         {
     87             dp[i][j]=min(dp[i-1][j],dp[i-1][j+(1<<(i-1))]);
     88         }
     89     }
     90 }
     91 int query(int t1,int t2)
     92 {
     93     t1=Rank[t1];
     94     t2=Rank[t2];
     95     if(t1>t2)
     96         swap(t1,t2);
     97     t1++;
     98     int tmp=log2(t2-t1+1);
     99     return min(dp[tmp][t1],dp[tmp][t2-(1<<tmp)+1]);
    100 }
    101 int main()
    102 {
    103     int T;
    104     scanf("%d",&T);
    105     while(T--)
    106     {
    107         char u;
    108         scanf("%d",&n);
    109         for(int i=0; i<n; i++)
    110         {
    111             getchar();
    112             scanf("%c",&u);
    113             ch[i]=u;
    114         }
    115 //cout<<ch<<endl;
    116         cal();
    117         rmq();
    118         int ans=0,t1,t2,t;
    119         for(int i=1; i<=n; i++)
    120         {
    121             for(int j=1; j+i<=n; j+=i)
    122             {
    123                 int tmp=query(j,j+i);
    124                 t1=i-tmp%i;
    125                 t2=j-t1;
    126                 t=tmp/i+1;
    127                 if(t2>0&&query(t2,t2+i)>=t1)
    128                     t++;
    129                 ans=max(ans,t);
    130             }
    131         }
    132         printf("%d
    ",ans);
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    分析Android中View的工作流程
    什么是分布式锁及正确使用redis实现分布式锁
    机器学习
    吴裕雄--天生自然诗经学习笔记 :醉蓬莱·渐亭皋叶下
    吴裕雄--天生自然诗经学习笔记 :节节高·题洞庭鹿角庙壁
    吴裕雄--天生自然诗经学习笔记 :浪淘沙
    吴裕雄--天生自然诗经学习笔记 :陇头歌辞三首
    吴裕雄--天生自然诗经学习笔记 :贾人食言
    吴裕雄--天生自然诗经学习笔记 :早秋三首
    吴裕雄--天生自然诗经学习笔记 :长相思·惜梅
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10394145.html
Copyright © 2011-2022 走看看