zoukankan      html  css  js  c++  java
  • hdu6194 string string string

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6194

    题目:

    string string string

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 486    Accepted Submission(s): 125


    Problem Description
    Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
    Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
     
    Input
    The first line contains an integer T (T100) implying the number of test cases.
    For each test case, there are two lines:
    the first line contains an integer k (k1) which is described above;
    the second line contain a string s (length(s)105).
    It's guaranteed that length(s)2106.
     
    Output
    For each test case, print the number of the important substrings in a line.
     
    Sample Input
    2 2 abcabc 3 abcabcabcabc
     
    Sample Output
    6 9
     
    Source
       
    思路:
      sam会卡指针版的代码,不明白卡这么点内存有什么意思。
      后缀自动机做法:建立sam后,统计出cnt数组,这一步要拓扑排序后倒着dp。
      后缀数组做法:用f[i][j]表示height(i,j)的区间最小值,然后滑动大小为k的窗口,则贡献是max(0,f[i][j]-max(height[i-1],height[j+1]) )
    后缀自动机做法:
     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 char ss[100004];
     6 int ans;
     7 
     8 struct SAM
     9 {
    10     static const int MAXN = 100001<<1;//大小为字符串长度两倍
    11     static const int LetterSize = 26;
    12 
    13     int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
    14     int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组
    15 
    16     void init( void)
    17     {
    18         last = tot = 1;
    19         len[1] = 0;
    20         memset(ch,0,sizeof ch);
    21         memset(fa,0,sizeof fa);
    22         memset(cnt,0,sizeof cnt);
    23     }
    24 
    25     void add( int x)
    26     {
    27         int p = last, np = last = ++tot;
    28         len[np] = len[p] + 1, cnt[last] = 1;
    29         while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
    30         if( p == 0)
    31             fa[np] = 1;
    32         else
    33         {
    34             int q = ch[p][x];
    35             if( len[q] == len[p] + 1)
    36                 fa[np] = q;
    37             else
    38             {
    39                 int nq = ++tot;
    40                 memcpy( ch[nq], ch[q], sizeof ch[q]);
    41                 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
    42                 while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
    43             }
    44         }
    45     }
    46 
    47     void toposort( void)
    48     {
    49         for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
    50         for(int i = 1; i <= tot; i++)   sum[len[i]]++;
    51         for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
    52         for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
    53     }
    54 } sam;
    55 
    56 
    57 int main(void)
    58 {
    59     //freopen("in.acm","r",stdin);
    60     int t,k;cin>>t;
    61     while(t--)
    62     {
    63         ans=0;
    64         sam.init();
    65         scanf("%d%s",&k,ss);
    66         for(int i=0,len=strlen(ss);i<len;i++)  sam.add(ss[i]-'a');
    67         sam.toposort();
    68         for(int i=sam.tot;i;i--)
    69         {
    70             int p=sam.tp[i],fp=sam.fa[p];
    71             sam.cnt[fp]+=sam.cnt[p];
    72             if(sam.cnt[p]==k)
    73                 ans+=sam.len[p]-sam.len[fp];
    74         }
    75         printf("%d
    ",ans);
    76     }
    77 
    78     return 0;
    79 }

    后缀数组做法:

     1 #include <cstdlib>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <set>
     6 #include <iostream>
     7 const int N = 200005;
     8 int sa[N],s[N],wa[N], wb[N], ws[N], wv[N];
     9 int rank[N], height[N];
    10 char ss[N];
    11 bool cmp(int r[], int a, int b, int l)
    12 {
    13     return r[a] == r[b] && r[a+l] == r[b+l];
    14 }
    15 
    16 void da(int r[], int sa[], int n, int m)
    17 {
    18     int i, j, p, *x = wa, *y = wb;
    19     for (i = 0; i < m; ++i) ws[i] = 0;
    20     for (i = 0; i < n; ++i) ws[x[i]=r[i]]++;
    21     for (i = 1; i < m; ++i) ws[i] += ws[i-1];
    22     for (i = n-1; i >= 0; --i) sa[--ws[x[i]]] = i;
    23     for (j = 1, p = 1; p < n; j *= 2, m = p)
    24     {
    25         for (p = 0, i = n - j; i < n; ++i) y[p++] = i;
    26         for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
    27         for (i = 0; i < n; ++i) wv[i] = x[y[i]];
    28         for (i = 0; i < m; ++i) ws[i] = 0;
    29         for (i = 0; i < n; ++i) ws[wv[i]]++;
    30         for (i = 1; i < m; ++i) ws[i] += ws[i-1];
    31         for (i = n-1; i >= 0; --i) sa[--ws[wv[i]]] = y[i];
    32         for (std::swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; ++i)
    33             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
    34     }
    35 }
    36 
    37 void calheight(int r[], int sa[], int n)
    38 {
    39     int i, j, k = 0;
    40     for (i = 1; i <= n; ++i) rank[sa[i]] = i;
    41     for (i = 0; i < n; height[rank[i++]] = k)
    42         for (k?k--:0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
    43 }
    44 struct RMQ
    45 {
    46     int log2[N],mi[N][25];
    47     void init(int n)
    48     {
    49         for(int i = 0; i <= n; i ++)log2[i] = (i == 0 ? -1 : log2[i >> 1] + 1);
    50         for(int j = 1; j < log2[n]; j ++)
    51             for(int i = 1; i + (1 << j) <= n + 1; i ++)
    52                 mi[i][j] = std::min(mi[i][j - 1], mi[i + (1 << j - 1)][j - 1]);
    53     }
    54     int query(int ql, int qr)
    55     {
    56         int k = log2[qr - ql + 1];
    57         return std::min(mi[ql][k], mi[qr - (1 << k) + 1][k]);
    58     }
    59 } rmq;
    60 int sc(int i,int k,int len)
    61 {
    62     if(k==1) return len-sa[i];
    63     return rmq.query(i+1,i+k-1);
    64 }
    65 int main()
    66 {
    67     int t,k;std::cin>>t;
    68     while(t--)
    69     {
    70         int ans=0;
    71         scanf("%d%s",&k,ss);
    72         int len=strlen(ss);
    73         for(int i=0;i<len;i++)
    74             s[i]=ss[i]-'a'+1;
    75         s[len]=0;
    76         da(s,sa,len+1,28);
    77         calheight(s,sa,len);
    78         height[len+1]=0;
    79         for(int i=1;i<=len;i++)
    80             rmq.mi[i][0]=height[i];
    81         rmq.init(len);
    82         for(int i=1;i<=len-k+1;i++)
    83             ans+=std::max(sc(i,k,len)-std::max(height[i],height[i+k]),0);
    84         printf("%d
    ",ans);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    HTML 照片从模糊到清晰的渐变加载显示方法
    Vue -- 从vue-cli 到@vue/cli 安装
    Vue -- highcharts map使用
    Vue -- admin
    EXCEL根据行列值查询得到交叉点值的方法
    如何使用curl命令测试负载均衡SLB会话保持的有效性
    centos7 pdsh安装
    selenium调用Chrome时自动选择证书
    jenkins使用 HTML Publisher插件后查看 html 报告显示不正常
    spring boot Jackson忽略字段不序列化字段
  • 原文地址:https://www.cnblogs.com/weeping/p/7503972.html
Copyright © 2011-2022 走看看